diff --git a/.changeset/entries/1fd815be9372a13668455bb550707d515b63dd90fceb597e339f5e732b702bbb.yaml b/.changeset/entries/1fd815be9372a13668455bb550707d515b63dd90fceb597e339f5e732b702bbb.yaml new file mode 100644 index 0000000000..b90ab99635 --- /dev/null +++ b/.changeset/entries/1fd815be9372a13668455bb550707d515b63dd90fceb597e339f5e732b702bbb.yaml @@ -0,0 +1,6 @@ +type: refactor +module: x/profiles +pull_request: 728 +description: Changed the subspace id type from string to uint64 +backward_compatible: false +date: 2022-01-24T15:00:42.365992872Z diff --git a/.changeset/entries/7804abd9534fe93894ef9a0bba10c1e28531dfd3420616246ebcdbe0c889326f.yaml b/.changeset/entries/7804abd9534fe93894ef9a0bba10c1e28531dfd3420616246ebcdbe0c889326f.yaml new file mode 100644 index 0000000000..fa9b8c157e --- /dev/null +++ b/.changeset/entries/7804abd9534fe93894ef9a0bba10c1e28531dfd3420616246ebcdbe0c889326f.yaml @@ -0,0 +1,6 @@ +type: feat +module: x/subspaces +pull_request: 728 +description: Added the new `x/subspaces` module +backward_compatible: false +date: 2022-01-24T11:13:39.102634771Z diff --git a/app/app.go b/app/app.go index bc508d1fec..6984b77bf6 100644 --- a/app/app.go +++ b/app/app.go @@ -8,6 +8,8 @@ import ( "path/filepath" "strings" + "github.com/desmos-labs/desmos/v2/x/subspaces" + "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/auth/vesting" @@ -84,6 +86,8 @@ import ( "github.com/desmos-labs/desmos/v2/x/profiles" profileskeeper "github.com/desmos-labs/desmos/v2/x/profiles/keeper" profilestypes "github.com/desmos-labs/desmos/v2/x/profiles/types" + subspaceskeeper "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + subspacestypes "github.com/desmos-labs/desmos/v2/x/subspaces/types" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" @@ -209,6 +213,7 @@ var ( // Custom modules profiles.AppModuleBasic{}, + subspaces.AppModuleBasic{}, ) // Module account permissions @@ -268,7 +273,8 @@ type DesmosApp struct { ScopedWasmKeeper capabilitykeeper.ScopedKeeper // Custom modules - ProfileKeeper profileskeeper.Keeper + SubspacesKeeper subspaceskeeper.Keeper + ProfileKeeper profileskeeper.Keeper // Module Manager mm *module.Manager @@ -315,7 +321,7 @@ func NewDesmosApp( authzkeeper.StoreKey, wasm.StoreKey, // Custom modules - profilestypes.StoreKey, + subspacestypes.StoreKey, profilestypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -405,17 +411,21 @@ func NewDesmosApp( ) transferModule := ibctransfer.NewAppModule(app.TransferKeeper) + // Create subspaces keeper + app.SubspacesKeeper = subspaceskeeper.NewKeeper(app.appCodec, keys[subspacestypes.StoreKey]) + // Create profiles keeper app.ProfileKeeper = profileskeeper.NewKeeper( app.appCodec, keys[profilestypes.StoreKey], app.GetSubspace(profilestypes.ModuleName), app.AccountKeeper, + app.SubspacesKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, scopedProfilesKeeper, ) - profilesModule := profiles.NewAppModule(appCodec, legacyAmino, app.ProfileKeeper, app.AccountKeeper, app.BankKeeper) + profilesModule := profiles.NewAppModule(appCodec, legacyAmino, app.ProfileKeeper, app.SubspacesKeeper, app.AccountKeeper, app.BankKeeper) // Create static IBC router, add transfer route, then set and seal it ibcRouter := porttypes.NewRouter() @@ -513,6 +523,7 @@ func NewDesmosApp( wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper), // Custom modules + subspaces.NewAppModule(appCodec, app.SubspacesKeeper, app.AccountKeeper, app.BankKeeper), profilesModule, ) @@ -540,7 +551,7 @@ func NewDesmosApp( feegrant.ModuleName, wasm.ModuleName, // Custom modules - profilestypes.ModuleName, + subspacestypes.ModuleName, profilestypes.ModuleName, crisistypes.ModuleName, ) @@ -575,7 +586,8 @@ func NewDesmosApp( wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper), // Custom modules - profiles.NewAppModule(app.appCodec, legacyAmino, app.ProfileKeeper, app.AccountKeeper, app.BankKeeper), + subspaces.NewAppModule(app.appCodec, app.SubspacesKeeper, app.AccountKeeper, app.BankKeeper), + profiles.NewAppModule(app.appCodec, legacyAmino, app.ProfileKeeper, app.SubspacesKeeper, app.AccountKeeper, app.BankKeeper), ) app.sm.RegisterStoreDecoders() @@ -767,7 +779,8 @@ func (app *DesmosApp) RegisterTendermintService(clientCtx client.Context) { } func (app *DesmosApp) registerUpgradeHandlers() { - app.UpgradeKeeper.SetUpgradeHandler("v2.3.1", func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + app.UpgradeKeeper.SetUpgradeHandler("v3.0.0", func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + // Nothing to do here for the x/subspaces module since the InitGenesis will be called return app.mm.RunMigrations(ctx, app.configurator, fromVM) }) @@ -776,8 +789,13 @@ func (app *DesmosApp) registerUpgradeHandlers() { panic(err) } - if upgradeInfo.Name == "v2.3.1" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { - storeUpgrades := storetypes.StoreUpgrades{} + if upgradeInfo.Name == "v3.0.0" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + storeUpgrades := storetypes.StoreUpgrades{ + Added: []string{ + wasm.ModuleName, + subspacestypes.ModuleName, + }, + } // Configure store loader that checks if version == upgradeHeight and applies store upgrades app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) diff --git a/app/params/weights.go b/app/params/weights.go index adcd8cf183..f970c887ec 100644 --- a/app/params/weights.go +++ b/app/params/weights.go @@ -2,13 +2,6 @@ package params // Default simulation operation weights for messages const ( - DefaultWeightMsgCreatePost int = 100 - DefaultWeightMsgEditPost int = 75 - DefaultWeightMsgAddReaction int = 80 - DefaultWeightMsgRemoveReaction int = 40 - DefaultWeightMsgAnswerPoll int = 20 - DefaultWeightMsgRegisterReaction int = 50 - DefaultWeightMsgSaveProfile int = 80 DefaultWeightMsgDeleteProfile int = 20 DefaultWeightMsgRequestDTagTransfer int = 85 @@ -21,14 +14,14 @@ const ( DefaultWeightMsgBlockUser int = 50 DefaultWeightMsgUnblockUser int = 50 - DefaultWeightMsgReportPost int = 50 - - DefaultWeightMsgCreateSubspace int = 100 - DefaultWeightMsgEditSubspace int = 75 - DefaultWeightMsgAddAmin int = 40 - DefaultWeightMsgRemoveAdmin int = 40 - DefaultWeightMsgRegisterUser int = 60 - DefaultWeightMsgUnregisterUser int = 50 - DefaultWeightMsgBanUser int = 30 - DefaultWeightMsgUnbanUser int = 20 + DefaultWeightMsgCreateSubspace int = 80 + DefaultWeightMsgEditSubspace int = 30 + DefaultWeightMsgDeleteSubspace int = 5 + DefaultWeightMsgCreateUserGroup int = 10 + DefaultWeightMsgEditUserGroup int = 30 + DefaultWeightMsgSetUserGroupPermissions int = 50 + DefaultWeightMsgDeleteUserGroup int = 5 + DefaultWeightMsgAddUserToUserGroup int = 7 + DefaultWeightMsgRemoveUserFromUserGroup int = 3 + DefaultWeightMsgSetUserPermissions int = 85 ) diff --git a/app/sim_test.go b/app/sim_test.go index 016a53eb7c..4c3cd81158 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -8,6 +8,8 @@ import ( "path/filepath" "testing" + subspacestypes "github.com/desmos-labs/desmos/v2/x/subspaces/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" @@ -217,10 +219,12 @@ func TestAppImportExport(t *testing.T) { {app.keys[govtypes.StoreKey], newApp.keys[govtypes.StoreKey], [][]byte{}}, {app.keys[evidencetypes.StoreKey], newApp.keys[evidencetypes.StoreKey], [][]byte{}}, - {app.keys[profilestypes.StoreKey], newApp.keys[profilestypes.StoreKey], [][]byte{}}, {app.keys[capabilitytypes.StoreKey], newApp.keys[capabilitytypes.StoreKey], [][]byte{}}, {app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}}, {app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.StoreKey], [][]byte{}}, + + {app.keys[subspacestypes.StoreKey], newApp.keys[subspacestypes.StoreKey], [][]byte{}}, + {app.keys[profilestypes.StoreKey], newApp.keys[profilestypes.StoreKey], [][]byte{}}, } for _, skp := range storeKeysPrefixes { diff --git a/client/docs/config.json b/client/docs/config.json index e3538b3d4d..db0abdf66b 100644 --- a/client/docs/config.json +++ b/client/docs/config.json @@ -13,6 +13,9 @@ "Params": "ProfilesParams" } } + }, + { + "url": "./tmp-swagger-gen/desmos/subspaces/v1/query.swagger.json" } ] } \ No newline at end of file diff --git a/client/docs/swagger-ui/swagger.yaml b/client/docs/swagger-ui/swagger.yaml index dadc3f30c3..b474bf61f2 100644 --- a/client/docs/swagger-ui/swagger.yaml +++ b/client/docs/swagger-ui/swagger.yaml @@ -730,6 +730,9 @@ paths: description: >- reverse is set to true if results are to be returned in the descending order. + + + Since: cosmos-sdk 0.43 in: query required: false type: boolean @@ -1471,7 +1474,183 @@ paths: prove the ownership signature: - type: string + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the + type of the serialized + + protocol buffer message. This string must + contain at least + + one "/" character. The last segment of the URL's + path must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name + should be in a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the + binary all types that they + + expect it to use in the context of Any. However, + for URLs which use the + + scheme `http`, `https`, or no scheme, one can + optionally set up a type + + server that maps type URLs to message + definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup + results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently + available in the official + + protobuf release, and it is not used for type + URLs beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty + scheme) might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of + the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol + buffer message along with a + + URL that describes the type of the serialized + message. + + + Protobuf library provides support to pack/unpack Any + values in the form + + of utility functions or additional generated methods + of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will + by default use + + 'type.googleapis.com/full.type.name' as the type URL + and the unpack + + methods only use the fully qualified type name after + the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" + will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the + regular + + representation of the deserialized, embedded + message, with an + + additional field `@type` which contains the type + URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a + custom JSON + + representation, that representation will be embedded + adding a field + + `value` which holds the custom JSON in addition to + the `@type` + + field. Example (for message + [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } title: >- Signature represents the hex-encoded signature of the PlainText value @@ -1479,7 +1658,9 @@ paths: type: string title: >- PlainText represents the hex-encoded value signed in - order to produce the Signature + order to produce the + + Signature chain_config: title: >- ChainConfig contains the configuration of the external @@ -1778,6 +1959,9 @@ paths: description: >- reverse is set to true if results are to be returned in the descending order. + + + Since: cosmos-sdk 0.43 in: query required: false type: boolean @@ -2171,70 +2355,247 @@ paths: prove the ownership signature: - type: string - title: >- - Signature represents the hex-encoded signature of the - PlainText value - plain_text: - type: string - title: >- - PlainText represents the hex-encoded value signed in - order to produce the Signature - chain_config: - title: >- - ChainConfig contains the configuration of the external - chain - type: object - properties: - name: - type: string - description: >- - ChainConfig contains the data of the chain with which the - link is made. - creation_time: - type: string - format: date-time - title: >- - CreationTime represents the time in which the link has - been created - title: >- - ChainLink contains the data representing either an inter- or - cross- chain + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the + type of the serialized - link - title: >- - QueryUserChainLinkResponse contains the data that is returned when - querying a + protocol buffer message. This string must contain + at least - specific chain link - default: - description: An unexpected error response - schema: - type: object - properties: - error: - type: string - code: - type: integer - format: int32 - message: - type: string - details: - type: array - items: - type: object - properties: - type_url: - type: string - description: >- - A URL/resource name that uniquely identifies the type of - the serialized + one "/" character. The last segment of the URL's + path must represent - protocol buffer message. This string must contain at - least + the fully qualified name of the type (as in - one "/" character. The last segment of the URL's path - must represent + `path/google.protobuf.Duration`). The name should + be in a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the + binary all types that they + + expect it to use in the context of Any. However, + for URLs which use the + + scheme `http`, `https`, or no scheme, one can + optionally set up a type + + server that maps type URLs to message definitions + as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results + based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently + available in the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty + scheme) might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the + above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any + values in the form + + of utility functions or additional generated methods + of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL + and the unpack + + methods only use the fully qualified type name after + the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will + yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the + regular + + representation of the deserialized, embedded message, + with an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a + custom JSON + + representation, that representation will be embedded + adding a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message + [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: >- + Signature represents the hex-encoded signature of the + PlainText value + plain_text: + type: string + title: >- + PlainText represents the hex-encoded value signed in + order to produce the + + Signature + chain_config: + title: >- + ChainConfig contains the configuration of the external + chain + type: object + properties: + name: + type: string + description: >- + ChainConfig contains the data of the chain with which the + link is made. + creation_time: + type: string + format: date-time + title: >- + CreationTime represents the time in which the link has + been created + title: >- + ChainLink contains the data representing either an inter- or + cross- chain + + link + title: >- + QueryUserChainLinkResponse contains the data that is returned when + querying a + + specific chain link + default: + description: An unexpected error response + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent the fully qualified name of the type (as in @@ -2747,6 +3108,9 @@ paths: description: >- reverse is set to true if results are to be returned in the descending order. + + + Since: cosmos-sdk 0.43 in: query required: false type: boolean @@ -3481,6 +3845,7 @@ paths: blocked for. subspace: type: string + format: uint64 title: >- Subspace contains the ID of the subspace inside which the user should be @@ -3720,6 +4085,7 @@ paths: in: query required: false type: string + format: uint64 - name: pagination.key description: |- key is a value returned in PageResponse.next_key to begin @@ -3771,6 +4137,9 @@ paths: description: >- reverse is set to true if results are to be returned in the descending order. + + + Since: cosmos-sdk 0.43 in: query required: false type: boolean @@ -3800,6 +4169,7 @@ paths: type: string subspace: type: string + format: uint64 description: >- Relationship is the struct of a relationship. @@ -4035,6 +4405,7 @@ paths: in: query required: false type: string + format: uint64 - name: pagination.key description: |- key is a value returned in PageResponse.next_key to begin @@ -4086,39 +4457,720 @@ paths: description: >- reverse is set to true if results are to be returned in the descending order. + + + Since: cosmos-sdk 0.43 in: query required: false type: boolean format: boolean tags: - Query -definitions: - cosmos.base.query.v1beta1.PageRequest: - type: object - properties: - key: - type: string - format: byte - description: |- - key is a value returned in PageResponse.next_key to begin - querying the next page most efficiently. Only one of offset or key - should be set. - offset: - type: string - format: uint64 - description: |- - offset is a numeric offset that can be used when key is unavailable. - It is less efficient than using key. Only one of offset or key should - be set. - limit: - type: string - format: uint64 - description: >- - limit is the total number of results to be returned in the result - page. - - If left empty it will default to a value to be set by each app. - count_total: + /desmos/subspaces/v1/subspaces: + get: + summary: Subspaces queries all the subspaces inside Desmos + operationId: Subspaces + responses: + '200': + description: A successful response. + schema: + type: object + properties: + subspaces: + type: array + items: + type: object + properties: + id: + type: string + format: uint64 + title: Unique id that identifies the subspace + name: + type: string + title: Human-readable name of the subspace + description: + type: string + title: Optional description of this subspace + treasury: + type: string + title: >- + Represents the account that is associated with the + subspace and + + should be used to connect external applications to + verify this subspace + owner: + type: string + title: Address of the user that owns the subspace + creator: + type: string + title: Address of the subspace creator + creation_time: + type: string + format: date-time + title: the creation time of the subspace + title: Subspace contains all the data of a Desmos subspace + pagination: + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: >- + PageResponse is to be embedded in gRPC response messages where + the + + corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } + title: >- + QuerySubspacesResponse is the response type for the + Query/Subspaces RPC + + method + default: + description: An unexpected error response + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: >- + offset is a numeric offset that can be used when key is unavailable. + + It is less efficient than using key. Only one of offset or key + should + + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: >- + count_total is set to true to indicate that the result set should + include + + a count of the total number of items available for pagination in + UIs. + + count_total is only respected when offset is used. It is ignored + when key + + is set. + in: query + required: false + type: boolean + format: boolean + - name: pagination.reverse + description: >- + reverse is set to true if results are to be returned in the + descending order. + + + Since: cosmos-sdk 0.43 + in: query + required: false + type: boolean + format: boolean + tags: + - Query + '/desmos/subspaces/v1/subspaces/{subspace_id}': + get: + summary: >- + Subspace queries all the information about the subspace with the given + id + operationId: Subspace + responses: + '200': + description: A successful response. + schema: + type: object + properties: + subspace: + type: object + properties: + id: + type: string + format: uint64 + title: Unique id that identifies the subspace + name: + type: string + title: Human-readable name of the subspace + description: + type: string + title: Optional description of this subspace + treasury: + type: string + title: >- + Represents the account that is associated with the + subspace and + + should be used to connect external applications to verify + this subspace + owner: + type: string + title: Address of the user that owns the subspace + creator: + type: string + title: Address of the subspace creator + creation_time: + type: string + format: date-time + title: the creation time of the subspace + title: Subspace contains all the data of a Desmos subspace + title: >- + QuerySubspaceResponse is the response type for the Query/Subspace + method + default: + description: An unexpected error response + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: subspace_id + in: path + required: true + type: string + format: uint64 + tags: + - Query + '/desmos/subspaces/v1/subspaces/{subspace_id}/groups': + get: + summary: >- + UserGroups queries all the groups that are present inside the subspace + with + + the given id + operationId: UserGroups + responses: + '200': + description: A successful response. + schema: + type: object + properties: + groups: + type: array + items: + type: object + properties: + subspace_id: + type: string + format: uint64 + id: + type: integer + format: int64 + title: Unique id that identifies the group + name: + type: string + title: Human-readable name of the user group + description: + type: string + permissions: + type: integer + format: int64 + title: UserGroup represents a group of users + pagination: + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: >- + PageResponse is to be embedded in gRPC response messages where + the + + corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } + title: >- + QueryUserGroupsResponse is the response type for the + Query/UserGroups RPC + + method + default: + description: An unexpected error response + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: subspace_id + in: path + required: true + type: string + format: uint64 + - name: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: >- + offset is a numeric offset that can be used when key is unavailable. + + It is less efficient than using key. Only one of offset or key + should + + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: >- + count_total is set to true to indicate that the result set should + include + + a count of the total number of items available for pagination in + UIs. + + count_total is only respected when offset is used. It is ignored + when key + + is set. + in: query + required: false + type: boolean + format: boolean + - name: pagination.reverse + description: >- + reverse is set to true if results are to be returned in the + descending order. + + + Since: cosmos-sdk 0.43 + in: query + required: false + type: boolean + format: boolean + tags: + - Query + '/desmos/subspaces/v1/subspaces/{subspace_id}/groups/{group_id}': + get: + summary: |- + UserGroup queries the user group having the given id inside the specific + subspace + operationId: UserGroup + responses: + '200': + description: A successful response. + schema: + type: object + properties: + group: + type: object + properties: + subspace_id: + type: string + format: uint64 + id: + type: integer + format: int64 + title: Unique id that identifies the group + name: + type: string + title: Human-readable name of the user group + description: + type: string + permissions: + type: integer + format: int64 + title: UserGroup represents a group of users + title: >- + QueryUserGroupResponse is the response type for the + Query/UserGroup RPC + + method + default: + description: An unexpected error response + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: subspace_id + in: path + required: true + type: string + format: uint64 + - name: group_id + in: path + required: true + type: integer + format: int64 + tags: + - Query + '/desmos/subspaces/v1/subspaces/{subspace_id}/groups/{group_id}/members': + get: + summary: UserGroupMembers queries all the members of a given user group + operationId: UserGroupMembers + responses: + '200': + description: A successful response. + schema: + type: object + properties: + members: + type: array + items: + type: string + pagination: + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: >- + PageResponse is to be embedded in gRPC response messages where + the + + corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } + title: |- + QueryUserGroupMembersResponse is the response type for the + Query/UserGroupMembers RPC method + default: + description: An unexpected error response + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: subspace_id + in: path + required: true + type: string + format: uint64 + - name: group_id + in: path + required: true + type: integer + format: int64 + - name: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: >- + offset is a numeric offset that can be used when key is unavailable. + + It is less efficient than using key. Only one of offset or key + should + + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: >- + count_total is set to true to indicate that the result set should + include + + a count of the total number of items available for pagination in + UIs. + + count_total is only respected when offset is used. It is ignored + when key + + is set. + in: query + required: false + type: boolean + format: boolean + - name: pagination.reverse + description: >- + reverse is set to true if results are to be returned in the + descending order. + + + Since: cosmos-sdk 0.43 + in: query + required: false + type: boolean + format: boolean + tags: + - Query + '/desmos/subspaces/v1/subspaces/{subspace_id}/permissions/{user}': + get: + summary: UserPermissions queries the permissions for the given user + operationId: UserPermissions + responses: + '200': + description: A successful response. + schema: + type: object + properties: + permissions: + type: integer + format: int64 + details: + type: array + items: + type: object + properties: + user: + title: User represents a user permission + type: object + properties: + user: + type: string + title: User for which the permission was set + permission: + type: integer + format: int64 + title: Permission set to the user + group: + title: Group represents a group permission + type: object + properties: + group_id: + type: integer + format: int64 + title: Error that is associated with the failure + permission: + type: integer + format: int64 + title: Permission set to the group + title: PermissionDetail contains the details data of a permission + title: |- + QueryUserPermissionsRequest is the response type for the + Query/UserPermissions method + default: + description: An unexpected error response + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: subspace_id + in: path + required: true + type: string + format: uint64 + - name: user + in: path + required: true + type: string + tags: + - Query +definitions: + cosmos.base.query.v1beta1.PageRequest: + type: object + properties: + key: + type: string + format: byte + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + offset: + type: string + format: uint64 + description: |- + offset is a numeric offset that can be used when key is unavailable. + It is less efficient than using key. Only one of offset or key should + be set. + limit: + type: string + format: uint64 + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + count_total: type: boolean format: boolean description: >- @@ -4137,6 +5189,9 @@ definitions: description: >- reverse is set to true if results are to be returned in the descending order. + + + Since: cosmos-sdk 0.43 description: |- message SomeRequest { Foo some_parameter = 1; @@ -4429,58 +5484,228 @@ definitions: 'type.googleapis.com/full.type.name' as the type URL and the unpack - methods only use the fully qualified type name after the last '/' + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: >- + Address contains the data of the external chain address to be + connected + + with the Desmos profile + proof: + title: Proof contains the ownership proof of the external chain address + type: object + properties: + pub_key: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of the + serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must + represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a + canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all + types that they + + expect it to use in the context of Any. However, for URLs + which use the + + scheme `http`, `https`, or no scheme, one can optionally set + up a type + + server that maps type URLs to message definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on + the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the + official + + protobuf release, and it is not used for type URLs beginning + with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) might + be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message + along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any + type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the last '/' - in the type URL, for example "foo.bar.com/x/y.z" will yield type + in the type URL, for example "foo.bar.com/x/y.z" will yield type - name "y.z". + name "y.z". - JSON + JSON - ==== + ==== - The JSON representation of an `Any` value uses the regular + The JSON representation of an `Any` value uses the regular - representation of the deserialized, embedded message, with an + representation of the deserialized, embedded message, with an - additional field `@type` which contains the type URL. Example: + additional field `@type` which contains the type URL. Example: - package google.profile; - message Person { - string first_name = 1; - string last_name = 2; - } + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } - { - "@type": "type.googleapis.com/google.profile.Person", - "firstName": , - "lastName": - } + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } - If the embedded message type is well-known and has a custom JSON + If the embedded message type is well-known and has a custom JSON - representation, that representation will be embedded adding a field + representation, that representation will be embedded adding a + field - `value` which holds the custom JSON in addition to the `@type` + `value` which holds the custom JSON in addition to the `@type` - field. Example (for message [google.protobuf.Duration][]): + field. Example (for message [google.protobuf.Duration][]): - { - "@type": "type.googleapis.com/google.protobuf.Duration", - "value": "1.212s" - } - title: >- - Address contains the data of the external chain address to be - connected + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: >- + PubKey represents the public key associated with the address for + which to - with the Desmos profile - proof: - title: Proof contains the ownership proof of the external chain address - type: object - properties: - pub_key: + prove the ownership + signature: type: object properties: type_url: @@ -4645,13 +5870,6 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } - title: >- - PubKey represents the public key associated with the address for - which to - - prove the ownership - signature: - type: string title: >- Signature represents the hex-encoded signature of the PlainText value @@ -4659,7 +5877,9 @@ definitions: type: string title: >- PlainText represents the hex-encoded value signed in order to - produce the Signature + produce the + + Signature chain_config: title: ChainConfig contains the configuration of the external chain type: object @@ -4902,54 +6122,218 @@ definitions: MinCount represents the minimum count of oracles that should complete the - verification successfully - prepare_gas: - type: string - format: uint64 - title: >- - PrepareGas represents the amount of gas to be used during the - preparation + verification successfully + prepare_gas: + type: string + format: uint64 + title: >- + PrepareGas represents the amount of gas to be used during the + preparation + + stage of the oracle script + execute_gas: + type: string + format: uint64 + title: >- + ExecuteGas represents the amount of gas to be used during the + execution of + + the oracle script + fee_amount: + type: array + items: + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + Coin defines a token with a denomination and an amount. + + + NOTE: The amount field is an Int which implements the custom + method + + signatures required by gogoproto. + title: >- + FeeAmount represents the amount of fees to be payed in order to + execute the + + oracle script + title: |- + OracleParams defines the parameters related to the oracle + that will be used to verify the ownership of a centralized + application account by a Desmos profile + title: Params contains the parameters for the profiles module + desmos.profiles.v1beta1.Proof: + type: object + properties: + pub_key: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of the + serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must + represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a + canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all types + that they + + expect it to use in the context of Any. However, for URLs which + use the + + scheme `http`, `https`, or no scheme, one can optionally set up a + type + + server that maps type URLs to message definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the + official + + protobuf release, and it is not used for type URLs beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above specified + type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along + with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: - stage of the oracle script - execute_gas: - type: string - format: uint64 - title: >- - ExecuteGas represents the amount of gas to be used during the - execution of + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } - the oracle script - fee_amount: - type: array - items: - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination and an amount. + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + If the embedded message type is well-known and has a custom JSON - NOTE: The amount field is an Int which implements the custom - method + representation, that representation will be embedded adding a field - signatures required by gogoproto. - title: >- - FeeAmount represents the amount of fees to be payed in order to - execute the + `value` which holds the custom JSON in addition to the `@type` - oracle script - title: |- - OracleParams defines the parameters related to the oracle - that will be used to verify the ownership of a centralized - application account by a Desmos profile - title: Params contains the parameters for the profiles module - desmos.profiles.v1beta1.Proof: - type: object - properties: - pub_key: + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: >- + PubKey represents the public key associated with the address for which + to + + prove the ownership + signature: type: object properties: type_url: @@ -5108,19 +6492,14 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } - title: >- - PubKey represents the public key associated with the address for which - to - - prove the ownership - signature: - type: string title: Signature represents the hex-encoded signature of the PlainText value plain_text: type: string title: >- PlainText represents the hex-encoded value signed in order to produce - the Signature + the + + Signature title: |- Proof contains all the data used to verify a signature when linking an account to a profile @@ -5389,6 +6768,7 @@ definitions: for. subspace: type: string + format: uint64 title: >- Subspace contains the ID of the subspace inside which the user should be @@ -5568,55 +6948,235 @@ definitions: in the type URL, for example "foo.bar.com/x/y.z" will yield type - name "y.z". + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a + field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: >- + Address contains the data of the external chain address to be + connected + + with the Desmos profile + proof: + title: Proof contains the ownership proof of the external chain address + type: object + properties: + pub_key: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". - JSON + JSON - ==== + ==== - The JSON representation of an `Any` value uses the regular + The JSON representation of an `Any` value uses the regular - representation of the deserialized, embedded message, with an + representation of the deserialized, embedded message, with + an - additional field `@type` which contains the type URL. Example: + additional field `@type` which contains the type URL. + Example: - package google.profile; - message Person { - string first_name = 1; - string last_name = 2; - } + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } - { - "@type": "type.googleapis.com/google.profile.Person", - "firstName": , - "lastName": - } + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } - If the embedded message type is well-known and has a custom JSON + If the embedded message type is well-known and has a custom + JSON - representation, that representation will be embedded adding a - field + representation, that representation will be embedded adding + a field - `value` which holds the custom JSON in addition to the `@type` + `value` which holds the custom JSON in addition to the + `@type` - field. Example (for message [google.protobuf.Duration][]): + field. Example (for message [google.protobuf.Duration][]): - { - "@type": "type.googleapis.com/google.protobuf.Duration", - "value": "1.212s" - } - title: >- - Address contains the data of the external chain address to be - connected + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: >- + PubKey represents the public key associated with the address + for which to - with the Desmos profile - proof: - title: Proof contains the ownership proof of the external chain address - type: object - properties: - pub_key: + prove the ownership + signature: type: object properties: type_url: @@ -5791,13 +7351,6 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } - title: >- - PubKey represents the public key associated with the address - for which to - - prove the ownership - signature: - type: string title: >- Signature represents the hex-encoded signature of the PlainText value @@ -5805,7 +7358,9 @@ definitions: type: string title: >- PlainText represents the hex-encoded value signed in order - to produce the Signature + to produce the + + Signature chain_config: title: ChainConfig contains the configuration of the external chain type: object @@ -6204,6 +7759,7 @@ definitions: type: string subspace: type: string + format: uint64 description: |- Relationship is the struct of a relationship. It represent the concept of "follow" of traditional social networks. @@ -6497,35 +8053,211 @@ definitions: string last_name = 2; } - { - "@type": "type.googleapis.com/google.profile.Person", - "firstName": , - "lastName": - } + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a + field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: >- + Address contains the data of the external chain address to be + connected + + with the Desmos profile + proof: + title: Proof contains the ownership proof of the external chain address + type: object + properties: + pub_key: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must + represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a + canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all + types that they + + expect it to use in the context of Any. However, for URLs + which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the + official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message + along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in + the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default + use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the last + '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } - If the embedded message type is well-known and has a custom JSON + If the embedded message type is well-known and has a custom + JSON - representation, that representation will be embedded adding a - field + representation, that representation will be embedded adding a + field - `value` which holds the custom JSON in addition to the `@type` + `value` which holds the custom JSON in addition to the `@type` - field. Example (for message [google.protobuf.Duration][]): + field. Example (for message [google.protobuf.Duration][]): - { - "@type": "type.googleapis.com/google.protobuf.Duration", - "value": "1.212s" - } - title: >- - Address contains the data of the external chain address to be - connected + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: >- + PubKey represents the public key associated with the address + for which to - with the Desmos profile - proof: - title: Proof contains the ownership proof of the external chain address - type: object - properties: - pub_key: + prove the ownership + signature: type: object properties: type_url: @@ -6696,13 +8428,6 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } - title: >- - PubKey represents the public key associated with the address - for which to - - prove the ownership - signature: - type: string title: >- Signature represents the hex-encoded signature of the PlainText value @@ -6710,7 +8435,9 @@ definitions: type: string title: >- PlainText represents the hex-encoded value signed in order to - produce the Signature + produce the + + Signature chain_config: title: ChainConfig contains the configuration of the external chain type: object @@ -6745,6 +8472,7 @@ definitions: type: string subspace: type: string + format: uint64 description: |- Relationship is the struct of a relationship. It represent the concept of "follow" of traditional social networks. @@ -6804,6 +8532,7 @@ definitions: description: Reason represents the optional reason the user has been blocked for. subspace: type: string + format: uint64 title: >- Subspace contains the ID of the subspace inside which the user should be @@ -7143,3 +8872,352 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + desmos.subspaces.v1.PermissionDetail: + type: object + properties: + user: + title: User represents a user permission + type: object + properties: + user: + type: string + title: User for which the permission was set + permission: + type: integer + format: int64 + title: Permission set to the user + group: + title: Group represents a group permission + type: object + properties: + group_id: + type: integer + format: int64 + title: Error that is associated with the failure + permission: + type: integer + format: int64 + title: Permission set to the group + title: PermissionDetail contains the details data of a permission + desmos.subspaces.v1.PermissionDetail.Group: + type: object + properties: + group_id: + type: integer + format: int64 + title: Error that is associated with the failure + permission: + type: integer + format: int64 + title: Permission set to the group + title: Group is a permission that has been set to a user group + desmos.subspaces.v1.PermissionDetail.User: + type: object + properties: + user: + type: string + title: User for which the permission was set + permission: + type: integer + format: int64 + title: Permission set to the user + title: Success is a permission that has been set to a specific user + desmos.subspaces.v1.QuerySubspaceResponse: + type: object + properties: + subspace: + type: object + properties: + id: + type: string + format: uint64 + title: Unique id that identifies the subspace + name: + type: string + title: Human-readable name of the subspace + description: + type: string + title: Optional description of this subspace + treasury: + type: string + title: >- + Represents the account that is associated with the subspace and + + should be used to connect external applications to verify this + subspace + owner: + type: string + title: Address of the user that owns the subspace + creator: + type: string + title: Address of the subspace creator + creation_time: + type: string + format: date-time + title: the creation time of the subspace + title: Subspace contains all the data of a Desmos subspace + title: QuerySubspaceResponse is the response type for the Query/Subspace method + desmos.subspaces.v1.QuerySubspacesResponse: + type: object + properties: + subspaces: + type: array + items: + type: object + properties: + id: + type: string + format: uint64 + title: Unique id that identifies the subspace + name: + type: string + title: Human-readable name of the subspace + description: + type: string + title: Optional description of this subspace + treasury: + type: string + title: >- + Represents the account that is associated with the subspace and + + should be used to connect external applications to verify this + subspace + owner: + type: string + title: Address of the user that owns the subspace + creator: + type: string + title: Address of the subspace creator + creation_time: + type: string + format: date-time + title: the creation time of the subspace + title: Subspace contains all the data of a Desmos subspace + pagination: + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: |- + PageResponse is to be embedded in gRPC response messages where the + corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } + title: |- + QuerySubspacesResponse is the response type for the Query/Subspaces RPC + method + desmos.subspaces.v1.QueryUserGroupMembersResponse: + type: object + properties: + members: + type: array + items: + type: string + pagination: + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: |- + PageResponse is to be embedded in gRPC response messages where the + corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } + title: |- + QueryUserGroupMembersResponse is the response type for the + Query/UserGroupMembers RPC method + desmos.subspaces.v1.QueryUserGroupResponse: + type: object + properties: + group: + type: object + properties: + subspace_id: + type: string + format: uint64 + id: + type: integer + format: int64 + title: Unique id that identifies the group + name: + type: string + title: Human-readable name of the user group + description: + type: string + permissions: + type: integer + format: int64 + title: UserGroup represents a group of users + title: |- + QueryUserGroupResponse is the response type for the Query/UserGroup RPC + method + desmos.subspaces.v1.QueryUserGroupsResponse: + type: object + properties: + groups: + type: array + items: + type: object + properties: + subspace_id: + type: string + format: uint64 + id: + type: integer + format: int64 + title: Unique id that identifies the group + name: + type: string + title: Human-readable name of the user group + description: + type: string + permissions: + type: integer + format: int64 + title: UserGroup represents a group of users + pagination: + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: |- + PageResponse is to be embedded in gRPC response messages where the + corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } + title: |- + QueryUserGroupsResponse is the response type for the Query/UserGroups RPC + method + desmos.subspaces.v1.QueryUserPermissionsResponse: + type: object + properties: + permissions: + type: integer + format: int64 + details: + type: array + items: + type: object + properties: + user: + title: User represents a user permission + type: object + properties: + user: + type: string + title: User for which the permission was set + permission: + type: integer + format: int64 + title: Permission set to the user + group: + title: Group represents a group permission + type: object + properties: + group_id: + type: integer + format: int64 + title: Error that is associated with the failure + permission: + type: integer + format: int64 + title: Permission set to the group + title: PermissionDetail contains the details data of a permission + title: |- + QueryUserPermissionsRequest is the response type for the + Query/UserPermissions method + desmos.subspaces.v1.Subspace: + type: object + properties: + id: + type: string + format: uint64 + title: Unique id that identifies the subspace + name: + type: string + title: Human-readable name of the subspace + description: + type: string + title: Optional description of this subspace + treasury: + type: string + title: >- + Represents the account that is associated with the subspace and + + should be used to connect external applications to verify this + subspace + owner: + type: string + title: Address of the user that owns the subspace + creator: + type: string + title: Address of the subspace creator + creation_time: + type: string + format: date-time + title: the creation time of the subspace + title: Subspace contains all the data of a Desmos subspace + desmos.subspaces.v1.UserGroup: + type: object + properties: + subspace_id: + type: string + format: uint64 + id: + type: integer + format: int64 + title: Unique id that identifies the group + name: + type: string + title: Human-readable name of the user group + description: + type: string + permissions: + type: integer + format: int64 + title: UserGroup represents a group of users diff --git a/docs/architecture/adr-006-subspace-module.md b/docs/architecture/adr-006-subspace-module.md index 1125482ff5..daa44d6164 100644 --- a/docs/architecture/adr-006-subspace-module.md +++ b/docs/architecture/adr-006-subspace-module.md @@ -5,13 +5,14 @@ - December 15th, 2021: Initial draft; - December 16th, 2021: First review; - January 06th, 2022: Second review; -- January 13th, 2021: Third review; -- January 14th, 2021: Fourth review; -- January 17th, 2021: Fifth review. +- January 13th, 2022: Third review; +- January 14th, 2022: Fourth review; +- January 17th, 2022: Fifth review; +- February 10th, 2022: Sixth review. ## Status -PROPOSED +ACCEPTED ## Abstract This ADR defines the `x/subspaces` module which allows users to create and manage the representation of different social networks inside which contents will be created. @@ -58,67 +59,84 @@ type Subspace struct { } ``` -#### ACL -In order to easily implement an ACL, we will use a simple set of keys made as follows: -``` -ACLPrefix + Subspace ID + -> ACL Value -``` +#### Permissions +Since each subspace is thought to represent an independent application, we SHOULD allow different subspaces owners to set different permissions for each user. -The `ACL Value` will be a simple binary value allowing us to perform bitwise operations to combine the following different permissions: +For this reason, we will implement an ACL (*Access Control List*) system that can be customized for each subspace. Each ACL MUST support setting permissions for both individual users and user groups. + +##### Permission value +To easily implement a composable system, we will use byte-based permissions: each value will be represented by an integer value, and composed permissions can be obtained by using the byte-wide *or* (`|`) operator. Also, this will allow us to easily check whether a user has a specific permission by using the byte-wide *and* (`&`) operator. ```go const ( - // Identifies users that can create content inside the subspace - PermissionWrite = 0b000001 - - // Allows users to moderate contents of other users (e.g. deleting it) - PermissionModerateContent = 0b000010 - - // Allows to add a link for this subspace - PermissionAddLink = 0b000100 - - // Allows to change the information of the subspace - PermissionChangeInfo = 0b001000 - - // Allows to set other users' permissions (except PermissionSetPermissions). - // This includes managing user groups and the associated permissions - PermissionSetPermissions = 0b010000 + // PermissionNothing represents the permission to do nothing + PermissionNothing = Permission(0b000000) + + // PermissionWrite identifies users that can create content inside the subspace + PermissionWrite = Permission(0b000001) + + // PermissionModerateContent allows users to moderate contents of other users (e.g. deleting it) + PermissionModerateContent = Permission(0b000010) + + // PermissionChangeInfo allows to change the information of the subspace + PermissionChangeInfo = Permission(0b000100) + + // PermissionManageGroups allows users to manage user groups and members + PermissionManageGroups = Permission(0b001000) + + // PermissionSetPermissions allows users to set other users' permissions (except PermissionSetPermissions). + // This includes managing user groups and the associated permissions + PermissionSetPermissions = Permission(0b010000) + + // PermissionDeleteSubspace allows users to delete the subspace. + PermissionDeleteSubspace = Permission(0b100000) + + // PermissionEverything allows to do everything. + // This should usually be reserved only to the owner (which has it by default) + PermissionEverything = Permission(0b111111) ) -``` - -> **Note**: -> Only the `Owner` account will be able to grant other users the `PermissionSetPermissions` -Using this kind of permissions will allow us to easily set permissions and check whether a user has a permission or not: -```go -userPermissions := PermissionWrite | PermissionAddLink | PermissionChangeInfo +userPermissions := PermissionWrite | PermissionManageGroups | PermissionChangeInfo canWrite := (userPermissions & PermissionWrite) == PermissionWrite // True canModerateContent := (userPermissions & PermissionModerateContent) == PermissionModerateContent // False ``` -##### Group permissions -In order to simplify the handling of multiple users' permissions, we SHOULD allow subspace admins to set group-wide permissions. -Each group will be represented by its own name, which can be defined by the admins themselves, and each group will have the same importance as others. -We reserve the group name `Others` to identify all the users that are not part of any other group (i.e. those users who are not registered inside a subspace). - -While checking a user permission to do something, the following actions will be performed: -1. get the permissions set for that specific user; -2. get all the permissions for all the groups the user is part of; -3. compute the resulting permission associated to the user using the `OR` operator. +> **Note**: +> Only the `Owner` account will be able to grant other users the `PermissionSetPermissions` -In order to properly store groups and members information, the following store keys will be used: -``` -// Store the belonging of a group to a subspace -SubspaceGroupPrefix + Subspace ID + Group name -> 0x01 +##### User groups +In order to properly implement user groups, we are going to define the following structure: + +```golang +type UserGroup struct { + // SubspaceID represents the ID of the subspace inside which the group exists + SubspaceID uint64 + // Unique id that identifies the group inside the subspace + ID uint32 + // Human-readable name of the user group + Name string + // Optional description of the group + Description string + // Permissions that will be granted to all the users inside this group + Permissions uint32 +} -// Store the belonging of a user to a specific subspace group -UserGroupPrefix + Subspace ID + Group name + User Address -> 0x01 ``` -In both cases, the `0x01` value is used only as a placeholder to make it possible for the key to exist. +The `ID` of each group will be a sequential value starting from `1` for each subspace. + +To store a group and its members, we will use the following key: +``` +GroupPrefix + SubspaceID + GroupID -> Group +``` +This will allow us to easily iterate over all the groups inside a subspace. -These keys will allow us to iterate over all the users that are part of a group as well as all the groups inside a subspace. This will allow clients to easily get all the groups of a subspace and the users that are part of such groups. On the other hand, it will make it harder to get all the groups that a user is part of. The decision to prioritize the first instead of the latter is made to make sure that permission checking is sufficiently fast: since subspace will have a limited amount of groups, it will be quite inexpensive to iterate over all of them and check if a given user is part of each group. +At the same time, to store each member of a group we will use the following store keys: +``` +GroupMemberPrefix + SubspaceID + GroupID + -> 0x01 +``` +In this case, the `0x01` value is just a placeholder that allows the key to exist. This key will allow us to easily iterate over all the members of a subspace, as well as to check whether a user is part of a group or not. ### `Msg` Service We will allow the following operations to be performed. @@ -126,14 +144,17 @@ We will allow the following operations to be performed. **Subspace administration** * Create a subspace * Edit a subspace +* Set a group's permissions +* Delete a subspace **Content management** * Delete contents that do not respect the ToS **Groups management** * Create a new group -* Delete a group +* Edit a group * Set group permissions +* Delete a group **Users management** * Add a user to a group @@ -153,7 +174,14 @@ service Msg { // CreateUserGroup allows to create a new user group rpc CreateUserGroup(MsgCreateUserGroup) returns (MsgCreateUserGroupResponse); - + + // EditUserGroup allows to edit a user group + rpc EditUserGroup(MsgEditUserGroup) returns (MsgEditUserGroupResponse); + + // SetUserGroupPermissions allows to set the permissions for a specific group + rpc SetUserGroupPermissions(MsgSetUserGroupPermissions) + returns (MsgSetUserGroupPermissionsResponse); + // DeleteUserGroup allows to delete an existing user group rpc DeleteUserGroup(MsgDeleteUserGroup) returns (MsgDeleteUserGroupResponse); @@ -164,14 +192,14 @@ service Msg { rpc RemoveUserFromUserGroup(MsgRemoveUserFromUserGroup) returns (MsgRemoveUserFromUserGroupResponse); // SetPermissions allows to set the permissions of a user or user group - rpc SetPermissions(MsgSetPermissions) returns (MsgSetPermissionsResponse); + rpc SetUserPermissions(MsgSetUserPermissions) returns (MsgSetUserPermissionsResponse); } message MsgCreateSubspace { string name = 1; string description = 2; - string owner = 3; - string treasury = 4; + string treasury = 3; + string owner = 4; string creator = 5; } @@ -180,28 +208,57 @@ message MsgCreateSubspaceResponse { } message MsgEditSubspace { - uint64 id = 1; + uint64 subspace_id = 1; string name = 2; string description = 3; - string owner = 4; - string treasury = 5; + string treasury = 4; + string owner = 5; string signer = 6; } message MsgEditSubspaceResponse {} +message MsgDeleteSubspace { + uint64 subspace_id = 1; + string signer = 2; +} + +message MsgDeleteSubspaceResponse {} + message MsgCreateUserGroup { uint64 subspace_id = 1; - string group_name = 2; - bytes default_permissions = 3; + string name = 2; + string description = 3; + bytes default_permissions = 4; + string creator = 5; +} + +message MsgCreateUserGroupResponse { + uint32 group_id = 1; +} + +message MsgEditUserGroup { + uint64 subspace_id = 1; + uint32 group_id = 2; + string name = 3; + string description = 4; + string signer = 5; +} + +message MsgEditUserGroupResponse {} + +message MsgSetUserGroupPermissions { + uint64 subspace_id = 1; + uint32 group_id = 2; + uint32 permissions = 3; string signer = 4; } -message MsgCreateUserGroupResponse {} +message MsgSetUserGroupPermissionsResponse {} message MsgDeleteUserGroup { uint64 subspace_id = 1; - string group_name = 2; + uint32 group_id = 2; string signer = 3; } @@ -209,8 +266,8 @@ message MsgDeleteUserGroupResponse {} message MsgAddUserToUserGroup { uint64 subspace_id = 1; - string user = 2; - string group_name = 3; + uint32 group_id = 2; + string user = 3; string signer = 4; } @@ -218,21 +275,21 @@ message MsgAddUserToUserGroupResponse {} message MsgRemoveUserFromUserGroup { uint64 subspace_id = 1; - string user = 2; - string group_name = 3; + uint32 group_id = 2; + string user = 3; string signer = 4; } message MsgRemoveUserFromUserGroupResponse {} -message MsgSetPermissions { +message MsgSetUserPermissions { uint64 subspace_id = 1; - string target = 2; + string user = 2; bytes permissions = 3; string signer = 4; } -message MsgSetPermissionsResponse {} +message MsgSetUserPermissionsResponse {} ``` ## Consequences diff --git a/go.mod b/go.mod index 7dd2145cd5..c7b6a27487 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/desmos-labs/desmos/v2 -go 1.15 +go 1.17 require ( github.com/CosmWasm/wasmd v0.21.1-0.20220105132732-3d2affb31f82 @@ -31,6 +31,100 @@ require ( gopkg.in/yaml.v2 v2.4.0 ) +require ( + filippo.io/edwards25519 v1.0.0-beta.2 // indirect + github.com/99designs/keyring v1.1.6 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/CosmWasm/wasmvm v1.0.0-beta5 // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/Workiva/go-datastructures v1.0.53 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect + github.com/coinbase/rosetta-sdk-go v0.6.10 // indirect + github.com/confio/ics23/go v0.6.6 // indirect + github.com/cosmos/btcutil v1.0.4 // indirect + github.com/cosmos/iavl v0.17.3 // indirect + github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect + github.com/cosmos/ledger-go v0.9.2 // indirect + github.com/danieljoos/wincred v1.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect + github.com/dgraph-io/badger/v2 v2.2007.2 // indirect + github.com/dgraph-io/ristretto v0.0.3 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect + github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.0 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/gateway v1.1.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/btree v1.0.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect + github.com/improbable-eng/grpc-web v0.14.1 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect + github.com/klauspost/compress v1.13.6 // indirect + github.com/lib/pq v1.10.4 // indirect + github.com/libp2p/go-buffer-pool v0.0.2 // indirect + github.com/magiconair/properties v1.8.5 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect + github.com/minio/highwayhash v1.0.2 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/pelletier/go-toml v1.9.4 // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect + github.com/rs/cors v1.8.0 // indirect + github.com/rs/zerolog v1.26.0 // indirect + github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect + github.com/spf13/afero v1.6.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.10.1 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect + github.com/tendermint/btcd v0.1.1 // indirect + github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/zondax/hid v0.9.0 // indirect + go.etcd.io/bbolt v1.3.6 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect + golang.org/x/net v0.0.0-20211005001312-d4b1ae081e3b // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect + golang.org/x/text v0.3.7 // indirect + gopkg.in/ini.v1 v1.66.2 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + nhooyr.io/websocket v1.8.6 // indirect +) + replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 replace github.com/cosmos/cosmos-sdk => github.com/desmos-labs/cosmos-sdk v0.43.0-alpha1.0.20211206072111-16bfceb83430 diff --git a/go.sum b/go.sum index 65a25702d4..0cc6be0cd1 100644 --- a/go.sum +++ b/go.sum @@ -377,7 +377,6 @@ github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= @@ -517,7 +516,6 @@ github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qH github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= @@ -848,10 +846,8 @@ github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnh github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ= github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.2 h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E= github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1686,7 +1682,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/proto/desmos/profiles/legacy/v230/models_chain_links.proto b/proto/desmos/profiles/legacy/v230/models_chain_links.proto index 27c4a9f7c9..ada3b144e6 100644 --- a/proto/desmos/profiles/legacy/v230/models_chain_links.proto +++ b/proto/desmos/profiles/legacy/v230/models_chain_links.proto @@ -66,7 +66,8 @@ message Proof { // Signature represents the hex-encoded signature of the PlainText value string signature = 2 [ (gogoproto.moretags) = "yaml:\"signature\"" ]; - // PlainText represents the hex-encoded value signed in order to produce the Signature + // PlainText represents the hex-encoded value signed in order to produce the + // Signature string plain_text = 3 [ (gogoproto.moretags) = "yaml:\"plain_text\"" ]; } @@ -106,6 +107,7 @@ message HexAddress { // Value represents the hex address value string value = 1 [ (gogoproto.moretags) = "yaml:\"value\"" ]; - // Prefix represents the optional prefix used during address encoding (e.g. 0x) + // Prefix represents the optional prefix used during address encoding (e.g. + // 0x) string prefix = 2 [ (gogoproto.moretags) = "yaml:\"prefix\"" ]; } \ No newline at end of file diff --git a/proto/desmos/profiles/legacy/v230/models_relationships.proto b/proto/desmos/profiles/legacy/v230/models_relationships.proto new file mode 100644 index 0000000000..13a41d4d08 --- /dev/null +++ b/proto/desmos/profiles/legacy/v230/models_relationships.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package desmos.profiles.legacy.v230; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/timestamp.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/desmos-labs/desmos/v2/x/profiles/legacy/v230"; + +// Relationship is the struct of a relationship. +// It represent the concept of "follow" of traditional social networks. +message Relationship { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = true; + + string creator = 1 [ (gogoproto.moretags) = "yaml:\"creator\"" ]; + string recipient = 2 [ (gogoproto.moretags) = "yaml:\"recipient\"" ]; + string subspace = 3 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; +} + +// UserBlock represents the fact that the Blocker has blocked the given Blocked +// user. +message UserBlock { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = true; + + // Blocker represents the address of the user blocking another one + string blocker = 1 [ (gogoproto.moretags) = "yaml:\"blocker\"" ]; + + // Blocked represents the address of the blocked user + string blocked = 2 [ (gogoproto.moretags) = "yaml:\"blocked\"" ]; + + // Reason represents the optional reason the user has been blocked for. + string reason = 3 [ (gogoproto.moretags) = "yaml:\"reason\"" ]; + + // Subspace contains the ID of the subspace inside which the user should be + // blocked + string subspace = 4 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; +} \ No newline at end of file diff --git a/proto/desmos/profiles/v1beta1/models_relationships.proto b/proto/desmos/profiles/v1beta1/models_relationships.proto index ac37d4be29..2e882a0509 100644 --- a/proto/desmos/profiles/v1beta1/models_relationships.proto +++ b/proto/desmos/profiles/v1beta1/models_relationships.proto @@ -17,7 +17,7 @@ message Relationship { string creator = 1 [ (gogoproto.moretags) = "yaml:\"creator\"" ]; string recipient = 2 [ (gogoproto.moretags) = "yaml:\"recipient\"" ]; - string subspace = 3 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; + uint64 subspace = 3 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; } // UserBlock represents the fact that the Blocker has blocked the given Blocked @@ -37,5 +37,5 @@ message UserBlock { // Subspace contains the ID of the subspace inside which the user should be // blocked - string subspace = 4 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; + uint64 subspace = 4 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; } diff --git a/proto/desmos/profiles/v1beta1/msgs_relationships.proto b/proto/desmos/profiles/v1beta1/msgs_relationships.proto index 4c32b756f9..3f51f03255 100644 --- a/proto/desmos/profiles/v1beta1/msgs_relationships.proto +++ b/proto/desmos/profiles/v1beta1/msgs_relationships.proto @@ -18,7 +18,7 @@ message MsgCreateRelationship { string sender = 1 [ (gogoproto.moretags) = "yaml:\"sender\"" ]; string receiver = 2 [ (gogoproto.moretags) = "yaml:\"receiver\"" ]; - string subspace = 3 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; + uint64 subspace = 3 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; } // MsgCreateRelationshipResponse defines the Msg/CreateRelationship response @@ -32,7 +32,7 @@ message MsgCreateRelationshipResponse {} message MsgDeleteRelationship { string user = 1 [ (gogoproto.moretags) = "yaml:\"user\"" ]; string counterparty = 2 [ (gogoproto.moretags) = "yaml:\"counterparty\"" ]; - string subspace = 3 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; + uint64 subspace = 3 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; } // MsgDeleteRelationshipResponse defines the Msg/DeleteRelationship response @@ -47,7 +47,7 @@ message MsgBlockUser { string blocker = 1 [ (gogoproto.moretags) = "yaml:\"blocker\"" ]; string blocked = 2 [ (gogoproto.moretags) = "yaml:\"blocked\"" ]; string reason = 3 [ (gogoproto.moretags) = "yaml:\"reason\"" ]; - string subspace = 4 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; + uint64 subspace = 4 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; } // MsgBlockUserResponse defines the Msg/BlockUser response type. @@ -59,7 +59,7 @@ message MsgBlockUserResponse {} message MsgUnblockUser { string blocker = 1 [ (gogoproto.moretags) = "yaml:\"blocker\"" ]; string blocked = 2 [ (gogoproto.moretags) = "yaml:\"blocked\"" ]; - string subspace = 4 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; + uint64 subspace = 4 [ (gogoproto.moretags) = "yaml:\"subspace\"" ]; } // MsgUnblockUserResponse defines the Msg/UnblockUser response type. diff --git a/proto/desmos/profiles/v1beta1/query_relationships.proto b/proto/desmos/profiles/v1beta1/query_relationships.proto index 5994d87e13..83554c4d31 100644 --- a/proto/desmos/profiles/v1beta1/query_relationships.proto +++ b/proto/desmos/profiles/v1beta1/query_relationships.proto @@ -20,7 +20,7 @@ message QueryRelationshipsRequest { string user = 1; // subspace to query the relationships for - string subspace_id = 2; + uint64 subspace_id = 2; // pagination defines an optional pagination for the request. cosmos.base.query.v1beta1.PageRequest pagination = 3; @@ -46,7 +46,7 @@ message QueryBlocksRequest { // address of the user to query the blocks for string user = 1; - string subspace_id = 2; + uint64 subspace_id = 2; cosmos.base.query.v1beta1.PageRequest pagination = 3; } diff --git a/proto/desmos/subspaces/v1/genesis.proto b/proto/desmos/subspaces/v1/genesis.proto new file mode 100644 index 0000000000..622ab901dc --- /dev/null +++ b/proto/desmos/subspaces/v1/genesis.proto @@ -0,0 +1,55 @@ +syntax = "proto3"; +package desmos.subspaces.v1; + +import "gogoproto/gogo.proto"; +import "desmos/subspaces/v1/models.proto"; + +option go_package = "github.com/desmos-labs/desmos/v2/x/subspaces/types"; + +// GenesisState contains the data of the genesis state for the subspaces module +message GenesisState { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = true; + + uint64 initial_subspace_id = 1 + [ (gogoproto.customname) = "InitialSubspaceID" ]; + + repeated GenesisSubspace subspaces = 2 [ (gogoproto.nullable) = false ]; + + repeated ACLEntry acl = 3 + [ (gogoproto.customname) = "ACL", (gogoproto.nullable) = false ]; + + repeated UserGroup user_groups = 4 [ (gogoproto.nullable) = false ]; + + repeated UserGroupMembersEntry user_groups_members = 5 + [ (gogoproto.nullable) = false ]; +} + +// GenesisSubspace contains the genesis data for a single subspace +message GenesisSubspace { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = true; + + Subspace subspace = 1 [ (gogoproto.nullable) = false ]; + uint32 initial_group_id = 2 [ (gogoproto.customname) = "InitialGroupID" ]; +} + +// ACLEntry represents a single Access Control List entry +message ACLEntry { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = true; + + uint64 subspace_id = 1 [ (gogoproto.customname) = "SubspaceID" ]; + string user = 2; + uint32 permissions = 3; +} + +// UserGroupMembersEntry contains all the members of a specific user group +message UserGroupMembersEntry { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = true; + + uint64 subspace_id = 1 [ (gogoproto.customname) = "SubspaceID" ]; + uint32 group_id = 2 [ (gogoproto.customname) = "GroupID" ]; + repeated string members = 3; +} \ No newline at end of file diff --git a/proto/desmos/subspaces/v1/models.proto b/proto/desmos/subspaces/v1/models.proto new file mode 100644 index 0000000000..2b68fec0ca --- /dev/null +++ b/proto/desmos/subspaces/v1/models.proto @@ -0,0 +1,108 @@ +syntax = "proto3"; +package desmos.subspaces.v1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/desmos-labs/desmos/v2/x/subspaces/types"; + +// Subspace contains all the data of a Desmos subspace +message Subspace { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = true; + + // Unique id that identifies the subspace + uint64 id = 1 + [ (gogoproto.customname) = "ID", (gogoproto.moretags) = "yaml:\"id\"" ]; + + // Human-readable name of the subspace + string name = 2 [ (gogoproto.moretags) = "yaml:\"name\"" ]; + + // Optional description of this subspace + string description = 3 [ (gogoproto.moretags) = "yaml:\"description\"" ]; + + // Represents the account that is associated with the subspace and + // should be used to connect external applications to verify this subspace + string treasury = 4 [ (gogoproto.moretags) = "yaml:\"treasury\"" ]; + + // Address of the user that owns the subspace + string owner = 5 [ (gogoproto.moretags) = "yaml:\"owner\"" ]; + + // Address of the subspace creator + string creator = 6 [ (gogoproto.moretags) = "yaml:\"creator\"" ]; + + // the creation time of the subspace + google.protobuf.Timestamp creation_time = 7 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true, + (gogoproto.moretags) = "yaml:\"creation_time\"" + ]; +} + +// UserGroup represents a group of users +message UserGroup { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = true; + + // ID of the subspace inside which this group exists + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + + // Unique id that identifies the group + uint32 id = 2 + [ (gogoproto.customname) = "ID", (gogoproto.moretags) = "yaml:\"id\"" ]; + + // Human-readable name of the user group + string name = 3 [ (gogoproto.moretags) = "yaml:\"name\"" ]; + + // Optional description of this group + string description = 4 [ (gogoproto.moretags) = "yaml:\"description\"" ]; + + // Permissions that will be granted to all the users part of this group + uint32 permissions = 5 [ (gogoproto.moretags) = "yaml:\"permissions\"" ]; +} + +// PermissionDetail contains the details data of a permission +message PermissionDetail { + option (gogoproto.goproto_getters) = false; + option (gogoproto.equal) = true; + + // sum is the oneof that specifies whether this represents a user or + // group permission detail + oneof sum { + // User represents a user permission + User user = 1; + + // Group represents a group permission + Group group = 2; + } + + // Success is a permission that has been set to a specific user + message User { + option (gogoproto.goproto_getters) = false; + option (gogoproto.equal) = true; + + // User for which the permission was set + string user = 1 [ (gogoproto.moretags) = "yaml:\"user\"" ]; + + // Permission set to the user + uint32 permission = 2 [ (gogoproto.moretags) = "yaml:\"permission\"" ]; + } + + // Group is a permission that has been set to a user group + message Group { + option (gogoproto.goproto_getters) = false; + option (gogoproto.equal) = true; + + // Error that is associated with the failure + uint32 group_id = 1 [ + (gogoproto.customname) = "GroupID", + (gogoproto.moretags) = "yaml:\"error\"" + ]; + + // Permission set to the group + uint32 permission = 2; + } +} \ No newline at end of file diff --git a/proto/desmos/subspaces/v1/msgs.proto b/proto/desmos/subspaces/v1/msgs.proto new file mode 100644 index 0000000000..170687bcfd --- /dev/null +++ b/proto/desmos/subspaces/v1/msgs.proto @@ -0,0 +1,257 @@ +syntax = "proto3"; +package desmos.subspaces.v1; + +import "gogoproto/gogo.proto"; +import "desmos/subspaces/v1/models.proto"; + +option go_package = "github.com/desmos-labs/desmos/v2/x/subspaces/types"; + +// Msg defines subspaces Msg service. +service Msg { + + // CreateSubspace allows to create a subspace + rpc CreateSubspace(MsgCreateSubspace) returns (MsgCreateSubspaceResponse); + + // EditSubspace allows to edit a subspace + rpc EditSubspace(MsgEditSubspace) returns (MsgEditSubspaceResponse); + + // DeleteSubspace allows to delete a subspace + rpc DeleteSubspace(MsgDeleteSubspace) returns (MsgDeleteSubspaceResponse); + + // CreateUserGroup allows to create a user group + rpc CreateUserGroup(MsgCreateUserGroup) returns (MsgCreateUserGroupResponse); + + // EditUserGroup allows to edit a user group + rpc EditUserGroup(MsgEditUserGroup) returns (MsgEditUserGroupResponse); + + // SetUserGroupPermissions allows to set the permissions for a specific group + rpc SetUserGroupPermissions(MsgSetUserGroupPermissions) + returns (MsgSetUserGroupPermissionsResponse); + + // DeleteUserGroup allows to delete an existing user group + rpc DeleteUserGroup(MsgDeleteUserGroup) returns (MsgDeleteUserGroupResponse); + + // AddUserToUserGroup allows to add a specific user to a specific user group + rpc AddUserToUserGroup(MsgAddUserToUserGroup) + returns (MsgAddUserToUserGroupResponse); + + // RemoveUserFromUserGroup allows to remove a specific user from a specific + // user group + rpc RemoveUserFromUserGroup(MsgRemoveUserFromUserGroup) + returns (MsgRemoveUserFromUserGroupResponse); + + // SetUserPermissions allows to set the permissions for a specific user + rpc SetUserPermissions(MsgSetUserPermissions) + returns (MsgSetUserPermissionsResponse); +} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgCreateSubspace represents the message used to create a subspace +message MsgCreateSubspace { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string name = 1 [ (gogoproto.moretags) = "yaml:\"name\"" ]; + string description = 2 [ (gogoproto.moretags) = "yaml:\"description\"" ]; + string treasury = 3 [ (gogoproto.moretags) = "yaml:\"treasury\"" ]; + string owner = 4 [ (gogoproto.moretags) = "yaml:\"owner\"" ]; + string creator = 5 [ (gogoproto.moretags) = "yaml:\"creator\"" ]; +} + +// MsgCreateSubspaceResponse defines the Msg/CreateSubspace response type +message MsgCreateSubspaceResponse { + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; +} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgEditSubspace represents the message used to edit a subspace fields +message MsgEditSubspace { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + + string name = 2 [ (gogoproto.moretags) = "yaml:\"name\"" ]; + string description = 3 [ (gogoproto.moretags) = "yaml:\"description\"" ]; + string treasury = 4 [ (gogoproto.moretags) = "yaml:\"treasury\"" ]; + string owner = 5 [ (gogoproto.moretags) = "yaml:\"owner\"" ]; + string signer = 6 [ (gogoproto.moretags) = "yaml:\"signer\"" ]; +} + +// MsgEditSubspaceResponse defines the Msg/EditSubspace response type +message MsgEditSubspaceResponse {} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgDeleteSubspace represents the message used to delete a subspace +message MsgDeleteSubspace { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + string signer = 2 [ (gogoproto.moretags) = "yaml:\"signer\"" ]; +} + +// MsgDeleteSubspaceResponse defines the Msg/DeleteSubspace response type +message MsgDeleteSubspaceResponse {} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgCreateUserGroup represents the message used to create a user group +message MsgCreateUserGroup { + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + + // Name of the group + string name = 2 [ (gogoproto.moretags) = "yaml:\"name\"" ]; + + // Optional description of the group + string description = 3 [ (gogoproto.moretags) = "yaml:\"description\"" ]; + + // Default permissions to be applied to the group + uint32 default_permissions = 4 + [ (gogoproto.moretags) = "yaml:\"default_permissions\"" ]; + + // Creator of the group + string creator = 5 [ (gogoproto.moretags) = "yaml:\"creator\"" ]; +} + +// MsgCreateUserGroupResponse defines the Msg/CreateUserGroup response type +message MsgCreateUserGroupResponse { + uint32 group_id = 1 [ + (gogoproto.customname) = "GroupID", + (gogoproto.moretags) = "yaml:\"group_id\"" + ]; +} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgEditUserGroup represents the message used to edit a user group +message MsgEditUserGroup { + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + uint32 group_id = 2 [ + (gogoproto.customname) = "GroupID", + (gogoproto.moretags) = "yaml:\"group_id\"" + ]; + string name = 3 [ (gogoproto.moretags) = "yaml:\"name\"" ]; + string description = 4 [ (gogoproto.moretags) = "yaml:\"description\"" ]; + string signer = 5 [ (gogoproto.moretags) = "yaml:\"signer\"" ]; +} + +// MsgEditUserGroupResponse defines the Msg/EditUserGroup response type +message MsgEditUserGroupResponse {} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgSetUserGroupPermissions represents the message used to set the permissions +// of a user group +message MsgSetUserGroupPermissions { + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + uint32 group_id = 2 [ + (gogoproto.customname) = "GroupID", + (gogoproto.moretags) = "yaml:\"group_id\"" + ]; + uint32 permissions = 3 [ (gogoproto.moretags) = "yaml:\"permissions\"" ]; + string signer = 4 [ (gogoproto.moretags) = "yaml:\"signer\"" ]; +} + +// MsgSetUserGroupPermissionsResponse defines the +// Msg/SetUserGroupPermissionsResponse response type +message MsgSetUserGroupPermissionsResponse {} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgDeleteUserGroup represents the message used to delete a user group +message MsgDeleteUserGroup { + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + uint32 group_id = 2 [ + (gogoproto.customname) = "GroupID", + (gogoproto.moretags) = "yaml:\"group_id\"" + ]; + string signer = 3 [ (gogoproto.moretags) = "yaml:\"signer\"" ]; +} + +// MsgDeleteUserGroupResponse defines the Msg/DeleteUserGroup response type +message MsgDeleteUserGroupResponse {} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgAddUserToUserGroup represents the message used to add a user to a user +// group +message MsgAddUserToUserGroup { + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + uint32 group_id = 2 [ + (gogoproto.customname) = "GroupID", + (gogoproto.moretags) = "yaml:\"group_id\"" + ]; + string user = 3 [ (gogoproto.moretags) = "yaml:\"user\"" ]; + string signer = 4 [ (gogoproto.moretags) = "yaml:\"signer\"" ]; +} + +// MsgAddUserToUserGroupResponse defines the Msg/AddUserToUserGroupResponse +// response type +message MsgAddUserToUserGroupResponse {} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgRemoveUserFromUserGroup represents the message used to remove a user from +// a user group +message MsgRemoveUserFromUserGroup { + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + uint32 group_id = 2 [ + (gogoproto.customname) = "GroupID", + (gogoproto.moretags) = "yaml:\"group_id\"" + ]; + string user = 3 [ (gogoproto.moretags) = "yaml:\"user\"" ]; + string signer = 4 [ (gogoproto.moretags) = "yaml:\"signer\"" ]; +} + +// MsgRemoveUserFromUserGroupResponse defines the +// Msg/RemoveUserFromUserGroupResponse response type +message MsgRemoveUserFromUserGroupResponse {} + +// -------------------------------------------------------------------------------------------------------------------- + +// MsgSetUserPermissions represents the message used to set the permissions of a +// specific user +message MsgSetUserPermissions { + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + string user = 2 [ (gogoproto.moretags) = "yaml:\"user\"" ]; + uint32 permissions = 3 [ (gogoproto.moretags) = "yaml:\"permissions\"" ]; + string signer = 4 [ (gogoproto.moretags) = "yaml:\"signer\"" ]; +} + +// MsgSetUserPermissionsResponse defines the Msg/SetPermissionsResponse +// response type +message MsgSetUserPermissionsResponse {} \ No newline at end of file diff --git a/proto/desmos/subspaces/v1/query.proto b/proto/desmos/subspaces/v1/query.proto new file mode 100644 index 0000000000..edf99643d3 --- /dev/null +++ b/proto/desmos/subspaces/v1/query.proto @@ -0,0 +1,155 @@ +syntax = "proto3"; +package desmos.subspaces.v1; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "desmos/subspaces/v1/models.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; + +option go_package = "github.com/desmos-labs/desmos/v2/x/subspaces/types"; + +// Query defines the gRPC querier service +service Query { + + // Subspaces queries all the subspaces inside Desmos + rpc Subspaces(QuerySubspacesRequest) returns (QuerySubspacesResponse) { + option (google.api.http).get = "/desmos/subspaces/v1/subspaces"; + } + + // Subspace queries all the information about the subspace with the given id + rpc Subspace(QuerySubspaceRequest) returns (QuerySubspaceResponse) { + option (google.api.http).get = + "/desmos/subspaces/v1/subspaces/{subspace_id}"; + } + + // UserGroups queries all the groups that are present inside the subspace with + // the given id + rpc UserGroups(QueryUserGroupsRequest) returns (QueryUserGroupsResponse) { + option (google.api.http).get = + "/desmos/subspaces/v1/subspaces/{subspace_id}/groups"; + } + + // UserGroup queries the user group having the given id inside the specific + // subspace + rpc UserGroup(QueryUserGroupRequest) returns (QueryUserGroupResponse) { + option (google.api.http).get = + "/desmos/subspaces/v1/subspaces/{subspace_id}/groups/{group_id}"; + } + + // UserGroupMembers queries all the members of a given user group + rpc UserGroupMembers(QueryUserGroupMembersRequest) + returns (QueryUserGroupMembersResponse) { + option (google.api.http).get = "/desmos/subspaces/v1/subspaces/" + "{subspace_id}/groups/{group_id}/members"; + } + + // UserPermissions queries the permissions for the given user + rpc UserPermissions(QueryUserPermissionsRequest) + returns (QueryUserPermissionsResponse) { + option (google.api.http).get = + "/desmos/subspaces/v1/subspaces/{subspace_id}/permissions/{user}"; + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +// QuerySubspacesRequest is the request type for the Query/Subspaces RPC method +message QuerySubspacesRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +// QuerySubspacesResponse is the response type for the Query/Subspaces RPC +// method +message QuerySubspacesResponse { + repeated Subspace subspaces = 1 [ (gogoproto.nullable) = false ]; + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// -------------------------------------------------------------------------------------------------------------------- + +// QuerySubspace is the request type for the Query/Subspace RPC method +message QuerySubspaceRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + uint64 subspace_id = 1 [ (gogoproto.moretags) = "yaml:\"subspace_id\"" ]; +} + +// QuerySubspaceResponse is the response type for the Query/Subspace method +message QuerySubspaceResponse { + desmos.subspaces.v1.Subspace subspace = 1 [ (gogoproto.nullable) = false ]; +} + +// -------------------------------------------------------------------------------------------------------------------- + +// QueryUserGroupsRequest is the request type for the Query/UserGroups RPC +// method +message QueryUserGroupsRequest { + uint64 subspace_id = 1 [ (gogoproto.moretags) = "yaml:\"subspace_id\"" ]; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryUserGroupsResponse is the response type for the Query/UserGroups RPC +// method +message QueryUserGroupsResponse { + repeated UserGroup groups = 1 [ (gogoproto.nullable) = false ]; + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// -------------------------------------------------------------------------------------------------------------------- + +// QueryUserGroupRequest is the request type for the Query/UserGroup RPC method +message QueryUserGroupRequest { + uint64 subspace_id = 1 [ (gogoproto.moretags) = "yaml:\"subspace_id\"" ]; + uint32 group_id = 2 [ (gogoproto.moretags) = "yaml:\"group_id\"" ]; +} + +// QueryUserGroupResponse is the response type for the Query/UserGroup RPC +// method +message QueryUserGroupResponse { + UserGroup group = 1 [ (gogoproto.nullable) = false ]; +} + +// -------------------------------------------------------------------------------------------------------------------- + +// QueryUserGroupMembersRequest is the request type for the +// Query/UserGroupMembers RPC method +message QueryUserGroupMembersRequest { + uint64 subspace_id = 1 [ (gogoproto.moretags) = "yaml:\"subspace_id\"" ]; + uint32 group_id = 2 [ (gogoproto.moretags) = "yaml:\"group_id\"" ]; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 3; +} + +// QueryUserGroupMembersResponse is the response type for the +// Query/UserGroupMembers RPC method +message QueryUserGroupMembersResponse { + repeated string members = 1; + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// -------------------------------------------------------------------------------------------------------------------- + +// QueryUserPermissionsRequest is the request type for the Query/UserPermissions +// RPC method +message QueryUserPermissionsRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + uint64 subspace_id = 1 [ (gogoproto.moretags) = "yaml:\"subspace_id\"" ]; + string user = 2 [ (gogoproto.moretags) = "yaml:\"user\"" ]; +} + +// QueryUserPermissionsRequest is the response type for the +// Query/UserPermissions method +message QueryUserPermissionsResponse { + uint32 permissions = 1 [ (gogoproto.moretags) = "yaml:\"permissions\"" ]; + repeated PermissionDetail details = 2 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"details\"" + ]; +} \ No newline at end of file diff --git a/x/profiles/client/cli/cli_relationships.go b/x/profiles/client/cli/cli_relationships.go index ec7d626f36..8fa7bb4ad8 100644 --- a/x/profiles/client/cli/cli_relationships.go +++ b/x/profiles/client/cli/cli_relationships.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + subspacestypes "github.com/desmos-labs/desmos/v2/x/subspaces/types" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" @@ -24,7 +26,12 @@ func GetCmdCreateRelationship() *cobra.Command { return err } - msg := types.NewMsgCreateRelationship(clientCtx.FromAddress.String(), args[0], args[1]) + subspaceID, err := subspacestypes.ParseSubspaceID(args[1]) + if err != nil { + return err + } + + msg := types.NewMsgCreateRelationship(clientCtx.FromAddress.String(), args[0], subspaceID) if err = msg.ValidateBasic(); err != nil { return fmt.Errorf("message validation failed: %w", err) } @@ -50,7 +57,12 @@ func GetCmdDeleteRelationship() *cobra.Command { return err } - msg := types.NewMsgDeleteRelationship(clientCtx.FromAddress.String(), args[0], args[1]) + subspaceID, err := subspacestypes.ParseSubspaceID(args[1]) + if err != nil { + return err + } + + msg := types.NewMsgDeleteRelationship(clientCtx.FromAddress.String(), args[0], subspaceID) if err = msg.ValidateBasic(); err != nil { return fmt.Errorf("message validation failed: %w", err) } @@ -76,12 +88,17 @@ func GetCmdBlockUser() *cobra.Command { return err } + subspaceID, err := subspacestypes.ParseSubspaceID(args[1]) + if err != nil { + return err + } + reason := "" if len(args) == 3 { reason = args[2] } - msg := types.NewMsgBlockUser(clientCtx.FromAddress.String(), args[0], reason, args[1]) + msg := types.NewMsgBlockUser(clientCtx.FromAddress.String(), args[0], reason, subspaceID) if err = msg.ValidateBasic(); err != nil { return fmt.Errorf("message validation failed: %w", err) } @@ -107,7 +124,12 @@ func GetCmdUnblockUser() *cobra.Command { return err } - msg := types.NewMsgUnblockUser(clientCtx.FromAddress.String(), args[0], args[1]) + subspaceID, err := subspacestypes.ParseSubspaceID(args[1]) + if err != nil { + return err + } + + msg := types.NewMsgUnblockUser(clientCtx.FromAddress.String(), args[0], subspaceID) if err = msg.ValidateBasic(); err != nil { return fmt.Errorf("message validation failed: %w", err) } @@ -141,9 +163,12 @@ func GetCmdQueryRelationships() *cobra.Command { user = args[0] } - var subspace string + var subspace uint64 if len(args) == 2 { - subspace = args[1] + subspace, err = subspacestypes.ParseSubspaceID(args[1]) + if err != nil { + return err + } } pageReq, err := client.ReadPageRequest(cmd.Flags()) @@ -187,9 +212,12 @@ func GetCmdQueryBlocks() *cobra.Command { user = args[0] } - var subspace string + var subspace uint64 if len(args) == 2 { - subspace = args[1] + subspace, err = subspacestypes.ParseSubspaceID(args[1]) + if err != nil { + return err + } } pageReq, err := client.ReadPageRequest(cmd.Flags()) diff --git a/x/profiles/client/cli/cli_relationships_test.go b/x/profiles/client/cli/cli_relationships_test.go index 7ab1a1435a..c66d3c99fb 100644 --- a/x/profiles/client/cli/cli_relationships_test.go +++ b/x/profiles/client/cli/cli_relationships_test.go @@ -34,7 +34,7 @@ func (s *IntegrationTestSuite) TestCmdQueryRelationships() { types.NewRelationship( "cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs", "cosmos1zs70glquczqgt83g03jnvcqppu4jjj8yjxwlvh", - "", + 0, ), }, Pagination: &query.PageResponse{ @@ -70,7 +70,7 @@ func (s *IntegrationTestSuite) TestCmdQueryRelationships() { types.NewRelationship( "cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs", "cosmos1zs70glquczqgt83g03jnvcqppu4jjj8yjxwlvh", - "", + 0, ), }, Pagination: &query.PageResponse{ @@ -123,7 +123,7 @@ func (s *IntegrationTestSuite) TestCmdQueryBlocks() { "cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs", "cosmos1zs70glquczqgt83g03jnvcqppu4jjj8yjxwlvh", "Test block", - "", + 0, ), }, Pagination: &query.PageResponse{ @@ -160,7 +160,7 @@ func (s *IntegrationTestSuite) TestCmdQueryBlocks() { "cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs", "cosmos1zs70glquczqgt83g03jnvcqppu4jjj8yjxwlvh", "Test block", - "", + 0, ), }, Pagination: &query.PageResponse{ diff --git a/x/profiles/client/cli/cli_test.go b/x/profiles/client/cli/cli_test.go index 32ea23a935..9b81df087c 100644 --- a/x/profiles/client/cli/cli_test.go +++ b/x/profiles/client/cli/cli_test.go @@ -121,14 +121,14 @@ func (s *IntegrationTestSuite) SetupSuite() { addr.String(), "cosmos1zs70glquczqgt83g03jnvcqppu4jjj8yjxwlvh", "Test block", - "", + 0, ), } profilesData.Relationships = []types.Relationship{ types.NewRelationship( addr.String(), "cosmos1zs70glquczqgt83g03jnvcqppu4jjj8yjxwlvh", - "", + 0, ), } profilesData.ApplicationLinks = []types.ApplicationLink{ diff --git a/x/profiles/keeper/common_test.go b/x/profiles/keeper/common_test.go index 09788032e5..41d4116cd8 100644 --- a/x/profiles/keeper/common_test.go +++ b/x/profiles/keeper/common_test.go @@ -4,6 +4,9 @@ import ( "testing" "time" + subspaceskeeper "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + subspacestypes "github.com/desmos-labs/desmos/v2/x/subspaces/types" + upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" @@ -51,6 +54,7 @@ type KeeperTestSuite struct { storeKey sdk.StoreKey k keeper.Keeper ak authkeeper.AccountKeeper + sk subspaceskeeper.Keeper paramsKeeper paramskeeper.Keeper stakingKeeper stakingkeeper.Keeper upgradeKeeper upgradekeeper.Keeper @@ -87,7 +91,10 @@ type TestData struct { func (suite *KeeperTestSuite) SetupTest() { // Define the store keys - keys := sdk.NewKVStoreKeys(types.StoreKey, authtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, capabilitytypes.StoreKey) + keys := sdk.NewKVStoreKeys( + types.StoreKey, subspacestypes.StoreKey, + authtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, capabilitytypes.StoreKey, + ) tKeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -139,11 +146,13 @@ func (suite *KeeperTestSuite) SetupTest() { scopedIBCKeeper, ) + suite.sk = subspaceskeeper.NewKeeper(suite.cdc, keys[subspacestypes.StoreKey]) suite.k = keeper.NewKeeper( suite.cdc, suite.storeKey, suite.paramsKeeper.Subspace(types.DefaultParamsSpace), suite.ak, + suite.sk, suite.IBCKeeper.ChannelKeeper, &suite.IBCKeeper.PortKeeper, scopedProfilesKeeper, diff --git a/x/profiles/keeper/expected_keeper.go b/x/profiles/keeper/expected_keeper.go new file mode 100644 index 0000000000..0b0f59a425 --- /dev/null +++ b/x/profiles/keeper/expected_keeper.go @@ -0,0 +1,16 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + subspacestypes "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// SubspacesKeeper represents the expected keeper used to interact with subspaces +type SubspacesKeeper interface { + // HasSubspace tells if the subspace with the given id exists + HasSubspace(ctx sdk.Context, subspaceID uint64) bool + + // GetAllSubspaces returns all the subspaces stored + GetAllSubspaces(ctx sdk.Context) []subspacestypes.Subspace +} diff --git a/x/profiles/keeper/genesis_test.go b/x/profiles/keeper/genesis_test.go index 77f65297ef..83ead876b1 100644 --- a/x/profiles/keeper/genesis_test.go +++ b/x/profiles/keeper/genesis_test.go @@ -58,12 +58,12 @@ func (suite *KeeperTestSuite) Test_ExportGenesis() { types.NewRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), } for _, rel := range relationships { @@ -75,13 +75,13 @@ func (suite *KeeperTestSuite) Test_ExportGenesis() { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewUserBlock( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), } for _, block := range blocks { @@ -151,12 +151,12 @@ func (suite *KeeperTestSuite) Test_ExportGenesis() { types.NewRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), }, []types.UserBlock{ @@ -164,13 +164,13 @@ func (suite *KeeperTestSuite) Test_ExportGenesis() { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewUserBlock( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), }, types.NewParams( @@ -268,8 +268,8 @@ func (suite *KeeperTestSuite) Test_InitGenesis() { genesis: types.NewGenesisState( nil, []types.Relationship{ - types.NewRelationship("creator", "recipient", "subspace"), - types.NewRelationship("creator", "recipient", "subspace"), + types.NewRelationship("creator", "recipient", 0), + types.NewRelationship("creator", "recipient", 0), }, []types.UserBlock{}, types.DefaultParams(), @@ -285,8 +285,8 @@ func (suite *KeeperTestSuite) Test_InitGenesis() { nil, []types.Relationship{}, []types.UserBlock{ - types.NewUserBlock("blocker", "blocked", "reason", "subspace"), - types.NewUserBlock("blocker", "blocked", "reason", "subspace"), + types.NewUserBlock("blocker", "blocked", "reason", 0), + types.NewUserBlock("blocker", "blocked", "reason", 0), }, types.DefaultParams(), "profiles-port-id", @@ -351,12 +351,12 @@ func (suite *KeeperTestSuite) Test_InitGenesis() { types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), }, []types.UserBlock{ @@ -364,13 +364,13 @@ func (suite *KeeperTestSuite) Test_InitGenesis() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewUserBlock( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), }, types.NewParams( @@ -427,12 +427,12 @@ func (suite *KeeperTestSuite) Test_InitGenesis() { types.NewRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), } suite.Require().Equal(relationships, suite.k.GetAllRelationships(ctx)) @@ -442,13 +442,13 @@ func (suite *KeeperTestSuite) Test_InitGenesis() { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewUserBlock( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), } suite.Require().Equal(blocks, suite.k.GetAllUsersBlocks(ctx)) diff --git a/x/profiles/keeper/grpc_query.go b/x/profiles/keeper/grpc_query.go index 6a4d6753b4..a7ccb1007c 100644 --- a/x/profiles/keeper/grpc_query.go +++ b/x/profiles/keeper/grpc_query.go @@ -91,7 +91,12 @@ func (k Keeper) Relationships(ctx context.Context, request *types.QueryRelations // Get user relationships prefix store store := sdkCtx.KVStore(k.storeKey) - relsStore := prefix.NewStore(store, types.UserRelationshipsSubspacePrefix(request.User, request.SubspaceId)) + + storePrefix := types.UserRelationshipsPrefix(request.User) + if request.User != "" { + storePrefix = types.UserRelationshipsSubspacePrefix(request.User, request.SubspaceId) + } + relsStore := prefix.NewStore(store, storePrefix) // Get paginated user relationships pageRes, err := query.Paginate(relsStore, request.Pagination, func(key []byte, value []byte) error { @@ -118,7 +123,12 @@ func (k Keeper) Blocks(ctx context.Context, request *types.QueryBlocksRequest) ( // Get user blocks prefix store store := sdkCtx.KVStore(k.storeKey) - userBlocksStore := prefix.NewStore(store, types.BlockerSubspacePrefix(request.User, request.SubspaceId)) + + storePrefix := types.BlockerPrefix(request.User) + if request.User != "" { + storePrefix = types.BlockerSubspacePrefix(request.User, request.SubspaceId) + } + userBlocksStore := prefix.NewStore(store, storePrefix) // Get paginated user blocks pageRes, err := query.Paginate(userBlocksStore, request.Pagination, func(key []byte, value []byte) error { diff --git a/x/profiles/keeper/grpc_query_test.go b/x/profiles/keeper/grpc_query_test.go index 7803589e42..7441949f0b 100644 --- a/x/profiles/keeper/grpc_query_test.go +++ b/x/profiles/keeper/grpc_query_test.go @@ -442,7 +442,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Relationships() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.SaveRelationship(ctx, relationship)) @@ -450,7 +450,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Relationships() { relationship = types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.SaveRelationship(ctx, relationship)) @@ -461,12 +461,12 @@ func (suite *KeeperTestSuite) TestQueryServer_Relationships() { types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), }, }, @@ -476,7 +476,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Relationships() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.SaveRelationship(ctx, relationship)) @@ -484,7 +484,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Relationships() { relationship = types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.SaveRelationship(ctx, relationship)) @@ -498,7 +498,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Relationships() { types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), }, }, @@ -539,7 +539,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Blocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason1", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.SaveUserBlock(ctx, block)) @@ -548,7 +548,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Blocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa", "reason2", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.SaveUserBlock(ctx, block)) @@ -560,13 +560,13 @@ func (suite *KeeperTestSuite) TestQueryServer_Blocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa", "reason2", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), types.NewUserBlock( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason1", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), }, }, @@ -577,7 +577,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Blocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason1", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.SaveUserBlock(ctx, block)) @@ -586,7 +586,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Blocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa", "reason2", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.SaveUserBlock(ctx, block)) @@ -601,7 +601,7 @@ func (suite *KeeperTestSuite) TestQueryServer_Blocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa", "reason2", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), }, }, diff --git a/x/profiles/keeper/invariants.go b/x/profiles/keeper/invariants.go index 7cc7df60e5..660e1df5f0 100644 --- a/x/profiles/keeper/invariants.go +++ b/x/profiles/keeper/invariants.go @@ -108,7 +108,7 @@ func formatOutputBlocks(invalidBlocks []types.UserBlock) (outputBlocks string) { outputBlocks = "The following list contains invalid user blocks:\n" for _, block := range invalidBlocks { outputBlocks += fmt.Sprintf( - "[Blocker]: %s, [Blocked]: %s, [Subspace]: %s\n", + "[Blocker]: %s, [Blocked]: %s, [Subspace]: %d\n", block.Blocker, block.Blocked, block.Subspace, ) } @@ -140,7 +140,7 @@ func formatOutputRelationships(relationships []types.Relationship) (output strin output = "The following list contains invalid relationships:\n" for _, relationship := range relationships { output += fmt.Sprintf( - "[Creator]: %s, [Recipient]: %s, [Subspace]: %s\n", + "[Creator]: %s, [Recipient]: %s, [Subspace]: %d\n", relationship.Creator, relationship.Recipient, relationship.Subspace, ) } diff --git a/x/profiles/keeper/invariants_test.go b/x/profiles/keeper/invariants_test.go index 800c82387c..f39a18fabf 100644 --- a/x/profiles/keeper/invariants_test.go +++ b/x/profiles/keeper/invariants_test.go @@ -52,7 +52,7 @@ func (suite *KeeperTestSuite) TestInvariants() { store: func(ctx sdk.Context) { store := ctx.KVStore(suite.storeKey) - block := types.NewUserBlock("blocker", "blocked", "reason", "subspace") + block := types.NewUserBlock("blocker", "blocked", "reason", 0) store.Set( types.UserBlockStoreKey(block.Blocker, block.Subspace, block.Blocked), suite.cdc.MustMarshal(&block), @@ -62,7 +62,7 @@ func (suite *KeeperTestSuite) TestInvariants() { expResponse: sdk.FormatInvariant(types.ModuleName, "invalid user blocks", fmt.Sprintf("%s%s", "The following list contains invalid user blocks:\n", - "[Blocker]: blocker, [Blocked]: blocked, [Subspace]: subspace\n", + "[Blocker]: blocker, [Blocked]: blocked, [Subspace]: 0\n", ), ), }, @@ -71,7 +71,7 @@ func (suite *KeeperTestSuite) TestInvariants() { store: func(ctx sdk.Context) { store := ctx.KVStore(suite.storeKey) - relationship := types.NewRelationship("creator", "recipient", "subspace") + relationship := types.NewRelationship("creator", "recipient", 0) store.Set( types.RelationshipsStoreKey(relationship.Creator, relationship.Subspace, relationship.Recipient), suite.cdc.MustMarshal(&relationship), @@ -81,7 +81,7 @@ func (suite *KeeperTestSuite) TestInvariants() { expResponse: sdk.FormatInvariant(types.ModuleName, "invalid relationships", fmt.Sprintf("%s%s", "The following list contains invalid relationships:\n", - "[Creator]: creator, [Recipient]: recipient, [Subspace]: subspace\n", + "[Creator]: creator, [Recipient]: recipient, [Subspace]: 0\n", ), ), }, diff --git a/x/profiles/keeper/keeper.go b/x/profiles/keeper/keeper.go index e8a36f4af0..a94da9b138 100644 --- a/x/profiles/keeper/keeper.go +++ b/x/profiles/keeper/keeper.go @@ -24,6 +24,7 @@ type Keeper struct { paramSubspace paramstypes.Subspace ak authkeeper.AccountKeeper + sk SubspacesKeeper channelKeeper types.ChannelKeeper portKeeper types.PortKeeper @@ -41,6 +42,7 @@ func NewKeeper( storeKey sdk.StoreKey, paramSpace paramstypes.Subspace, ak authkeeper.AccountKeeper, + sk SubspacesKeeper, channelKeeper types.ChannelKeeper, portKeeper types.PortKeeper, scopedKeeper types.ScopedKeeper, @@ -54,6 +56,7 @@ func NewKeeper( cdc: cdc, paramSubspace: paramSpace, ak: ak, + sk: sk, channelKeeper: channelKeeper, portKeeper: portKeeper, scopedKeeper: scopedKeeper, diff --git a/x/profiles/keeper/keeper_blocks.go b/x/profiles/keeper/keeper_blocks.go index 1ea6b0d4c6..5df338430a 100644 --- a/x/profiles/keeper/keeper_blocks.go +++ b/x/profiles/keeper/keeper_blocks.go @@ -60,13 +60,13 @@ func (k Keeper) GetAllUsersBlocks(ctx sdk.Context) []types.UserBlock { // IsUserBlocked tells if the given blocker has blocked the given blocked user func (k Keeper) IsUserBlocked(ctx sdk.Context, blocker, blocked string) bool { - return k.HasUserBlocked(ctx, blocker, blocked, "") + return k.HasUserBlocked(ctx, blocker, blocked, 0) } // HasUserBlocked returns true if the provided blocker has blocked the given user for the given subspace. // If the provided subspace is empty, all subspaces will be checked -func (k Keeper) HasUserBlocked(ctx sdk.Context, blocker, blocked, subspace string) bool { - if subspace != "" { +func (k Keeper) HasUserBlocked(ctx sdk.Context, blocker, blocked string, subspace uint64) bool { + if subspace != 0 { store := ctx.KVStore(k.storeKey) key := types.UserBlockStoreKey(blocker, subspace, blocked) @@ -76,7 +76,7 @@ func (k Keeper) HasUserBlocked(ctx sdk.Context, blocker, blocked, subspace strin blocks := k.GetUserBlocks(ctx, blocker) for _, block := range blocks { if block.Blocked == blocked { - return subspace == "" || block.Subspace == subspace + return subspace == 0 || block.Subspace == subspace } } @@ -84,12 +84,12 @@ func (k Keeper) HasUserBlocked(ctx sdk.Context, blocker, blocked, subspace strin } // DeleteUserBlock allows to the specified blocker to unblock the given blocked user. -func (k Keeper) DeleteUserBlock(ctx sdk.Context, blocker, blocked string, subspace string) error { +func (k Keeper) DeleteUserBlock(ctx sdk.Context, blocker, blocked string, subspace uint64) error { store := ctx.KVStore(k.storeKey) key := types.UserBlockStoreKey(blocker, subspace, blocked) if !store.Has(key) { return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, - "block from %s towards %s for subspace %s not found", blocker, blocked, subspace) + "block from %s towards %s for subspace %d not found", blocker, blocked, subspace) } store.Delete(key) return nil diff --git a/x/profiles/keeper/keeper_blocks_test.go b/x/profiles/keeper/keeper_blocks_test.go index 16421d2562..f4b280ecb4 100644 --- a/x/profiles/keeper/keeper_blocks_test.go +++ b/x/profiles/keeper/keeper_blocks_test.go @@ -22,7 +22,7 @@ func (suite *KeeperTestSuite) TestKeeper_IsUserBlocked() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "test", - "", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -69,7 +69,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveUserBlock() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos10nsdxxdvy9qka3zv0lzw8z9cnu6kanld8jh773", "reason", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -79,7 +79,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveUserBlock() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos10nsdxxdvy9qka3zv0lzw8z9cnu6kanld8jh773", "reason", - "subspace", + 0, ), shouldErr: true, }, @@ -93,7 +93,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveUserBlock() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "reason", - "subspace", + 0, ), shouldErr: false, check: func(ctx sdk.Context) { @@ -103,7 +103,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveUserBlock() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "reason", - "subspace", + 0, ), blocks[0]) }, }, @@ -137,7 +137,7 @@ func (suite *KeeperTestSuite) TestKeeper_DeleteUserBlock() { store func(ctx sdk.Context) blocker string blocked string - subspace string + subspace uint64 shouldErr bool check func(ctx sdk.Context) }{ @@ -148,7 +148,7 @@ func (suite *KeeperTestSuite) TestKeeper_DeleteUserBlock() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "reason", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -158,7 +158,7 @@ func (suite *KeeperTestSuite) TestKeeper_DeleteUserBlock() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", "reason", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -166,7 +166,7 @@ func (suite *KeeperTestSuite) TestKeeper_DeleteUserBlock() { }, blocker: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", blocked: "cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", - subspace: "subspace", + subspace: 0, shouldErr: false, check: func(ctx sdk.Context) { blocks := suite.k.GetUserBlocks(ctx, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47") @@ -180,7 +180,7 @@ func (suite *KeeperTestSuite) TestKeeper_DeleteUserBlock() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "reason", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -188,14 +188,14 @@ func (suite *KeeperTestSuite) TestKeeper_DeleteUserBlock() { }, blocker: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", blocked: "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - subspace: "subspace", + subspace: 0, shouldErr: false, }, { name: "deleting a user block that does not exist returns an error", blocker: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", blocked: "blocked", - subspace: "subspace", + subspace: 0, shouldErr: true, }, } @@ -236,7 +236,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetUserBlocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos10nsdxxdvy9qka3zv0lzw8z9cnu6kanld8jh773", "reason", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -248,7 +248,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetUserBlocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos10nsdxxdvy9qka3zv0lzw8z9cnu6kanld8jh773", "reason", - "subspace", + 0, ), }, }, @@ -286,7 +286,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetAllUsersBlocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "reason", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -296,7 +296,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetAllUsersBlocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", "reason", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -307,13 +307,13 @@ func (suite *KeeperTestSuite) TestKeeper_GetAllUsersBlocks() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "reason", - "subspace", + 0, ), types.NewUserBlock( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", "reason", - "subspace", + 0, ), }, }, @@ -343,7 +343,7 @@ func (suite *KeeperTestSuite) TestKeeper_HasUserBlocked() { store func(ctx sdk.Context) blocker string blocked string - subspace string + subspace uint64 expBlocked bool }{ { @@ -353,7 +353,7 @@ func (suite *KeeperTestSuite) TestKeeper_HasUserBlocked() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "reason", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -361,14 +361,14 @@ func (suite *KeeperTestSuite) TestKeeper_HasUserBlocked() { }, blocker: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", blocked: "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - subspace: "subspace", + subspace: 0, expBlocked: true, }, { name: "blocked user not found returns false", blocker: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", blocked: "blocked", - subspace: "subspace_2", + subspace: 1, expBlocked: false, }, } diff --git a/x/profiles/keeper/keeper_relationships.go b/x/profiles/keeper/keeper_relationships.go index 1ba9bc2e4d..f38c1fe3bb 100644 --- a/x/profiles/keeper/keeper_relationships.go +++ b/x/profiles/keeper/keeper_relationships.go @@ -7,6 +7,11 @@ import ( "github.com/desmos-labs/desmos/v2/x/profiles/types" ) +// HasSubspace tells if the subspace with the given id exists +func (k Keeper) HasSubspace(ctx sdk.Context, subspaceID uint64) bool { + return k.sk.HasSubspace(ctx, subspaceID) +} + // SaveRelationship allows to store the given relationship returning an error if he's already present. // It requires the creator to have a profile. func (k Keeper) SaveRelationship(ctx sdk.Context, relationship types.Relationship) error { @@ -32,7 +37,7 @@ func (k Keeper) SaveRelationship(ctx sdk.Context, relationship types.Relationshi } // GetRelationship returns the relationship existing between the provided creator and recipient inside the given subspace -func (k Keeper) GetRelationship(ctx sdk.Context, creator, subspace, recipient string) (types.Relationship, bool) { +func (k Keeper) GetRelationship(ctx sdk.Context, creator string, subspace uint64, recipient string) (types.Relationship, bool) { store := ctx.KVStore(k.storeKey) key := types.RelationshipsStoreKey(creator, subspace, recipient) @@ -69,7 +74,7 @@ func (k Keeper) RemoveRelationship(ctx sdk.Context, relationship types.Relations key := types.RelationshipsStoreKey(relationship.Creator, relationship.Subspace, relationship.Recipient) if !store.Has(key) { return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, - "relationship between %s and %s for subspace %s not found", + "relationship between %s and %s for subspace %d not found", relationship.Creator, relationship.Recipient, relationship.Subspace) } store.Delete(key) diff --git a/x/profiles/keeper/keeper_relationships_test.go b/x/profiles/keeper/keeper_relationships_test.go index 59b664974e..0846b25db8 100644 --- a/x/profiles/keeper/keeper_relationships_test.go +++ b/x/profiles/keeper/keeper_relationships_test.go @@ -21,7 +21,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveRelationship() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Recipient))) @@ -30,7 +30,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveRelationship() { relationship: types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ), shouldErr: true, }, @@ -43,7 +43,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveRelationship() { relationship: types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ), shouldErr: false, check: func(ctx sdk.Context) { @@ -51,7 +51,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveRelationship() { types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ), } suite.Require().Equal(expected, suite.k.GetAllRelationships(ctx)) @@ -63,7 +63,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveRelationship() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Recipient))) @@ -72,7 +72,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveRelationship() { relationship: types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace_2", + 1, ), shouldErr: false, }, @@ -82,7 +82,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveRelationship() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Recipient))) @@ -91,7 +91,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveRelationship() { relationship: types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", - "subspace_2", + 1, ), shouldErr: false, }, @@ -128,7 +128,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetAllRelationships() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Recipient))) @@ -137,7 +137,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetAllRelationships() { relationship = types.NewRelationship( "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Recipient))) @@ -147,12 +147,12 @@ func (suite *KeeperTestSuite) TestKeeper_GetAllRelationships() { types.NewRelationship( "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", - "subspace", + 0, ), types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ), }, }, @@ -189,7 +189,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetUserRelationships() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Recipient))) @@ -200,7 +200,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetUserRelationships() { types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ), }, }, @@ -238,7 +238,7 @@ func (suite *KeeperTestSuite) TestKeeper_RemoveRelationship() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Recipient))) @@ -247,7 +247,7 @@ func (suite *KeeperTestSuite) TestKeeper_RemoveRelationship() { relationship = types.NewRelationship( "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", - "subspace", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Recipient))) @@ -256,7 +256,7 @@ func (suite *KeeperTestSuite) TestKeeper_RemoveRelationship() { relationshipToDelete: types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ), shouldErr: false, check: func(ctx sdk.Context) { @@ -264,7 +264,7 @@ func (suite *KeeperTestSuite) TestKeeper_RemoveRelationship() { types.NewRelationship( "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", "cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", - "subspace", + 0, ), } suite.Require().Equal(expected, suite.k.GetAllRelationships(ctx)) @@ -275,7 +275,7 @@ func (suite *KeeperTestSuite) TestKeeper_RemoveRelationship() { relationshipToDelete: types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 0, ), shouldErr: true, }, diff --git a/x/profiles/keeper/migrations.go b/x/profiles/keeper/migrations.go index 5da56adf7d..c0309168f1 100644 --- a/x/profiles/keeper/migrations.go +++ b/x/profiles/keeper/migrations.go @@ -11,9 +11,9 @@ import ( "github.com/desmos-labs/desmos/v2/x/profiles/types" - v210 "github.com/desmos-labs/desmos/v2/x/profiles/legacy/v210" - v200 "github.com/desmos-labs/desmos/v2/x/profiles/legacy/v200" + v210 "github.com/desmos-labs/desmos/v2/x/profiles/legacy/v210" + v300 "github.com/desmos-labs/desmos/v2/x/profiles/legacy/v300" ) // DONTCOVER @@ -107,3 +107,8 @@ func (m Migrator) migrateProfile(ctx sdk.Context, profile *types.Profile) error m.keeper.ak.SetAccount(ctx, profile) return nil } + +// Migrate4to5 migrates from version 4 to 5. +func (m Migrator) Migrate4to5(ctx sdk.Context) error { + return v300.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc) +} diff --git a/x/profiles/keeper/msg_server_blocks.go b/x/profiles/keeper/msg_server_blocks.go index 57e82cf4a2..1405432111 100644 --- a/x/profiles/keeper/msg_server_blocks.go +++ b/x/profiles/keeper/msg_server_blocks.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "fmt" sdk "github.com/cosmos/cosmos-sdk/types" @@ -21,7 +22,7 @@ func (k msgServer) BlockUser(goCtx context.Context, msg *types.MsgBlockUser) (*t types.EventTypeBlockUser, sdk.NewAttribute(types.AttributeKeyUserBlockBlocker, msg.Blocker), sdk.NewAttribute(types.AttributeKeyUserBlockBlocked, msg.Blocked), - sdk.NewAttribute(types.AttributeKeySubspace, msg.Subspace), + sdk.NewAttribute(types.AttributeKeySubspace, fmt.Sprintf("%d", msg.Subspace)), sdk.NewAttribute(types.AttributeKeyUserBlockReason, msg.Reason), )) @@ -40,7 +41,7 @@ func (k msgServer) UnblockUser(goCtx context.Context, msg *types.MsgUnblockUser) types.EventTypeUnblockUser, sdk.NewAttribute(types.AttributeKeyUserBlockBlocker, msg.Blocker), sdk.NewAttribute(types.AttributeKeyUserBlockBlocked, msg.Blocked), - sdk.NewAttribute(types.AttributeKeySubspace, msg.Subspace), + sdk.NewAttribute(types.AttributeKeySubspace, fmt.Sprintf("%d", msg.Subspace)), )) return &types.MsgUnblockUserResponse{}, nil diff --git a/x/profiles/keeper/msg_server_blocks_test.go b/x/profiles/keeper/msg_server_blocks_test.go index 3ece25a3b0..4422f4ab98 100644 --- a/x/profiles/keeper/msg_server_blocks_test.go +++ b/x/profiles/keeper/msg_server_blocks_test.go @@ -25,7 +25,7 @@ func (suite *KeeperTestSuite) TestMsgServer_BlockUser() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -35,7 +35,7 @@ func (suite *KeeperTestSuite) TestMsgServer_BlockUser() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, ), shouldErr: true, }, @@ -49,7 +49,7 @@ func (suite *KeeperTestSuite) TestMsgServer_BlockUser() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, ), shouldErr: false, expEvents: sdk.Events{ @@ -57,7 +57,7 @@ func (suite *KeeperTestSuite) TestMsgServer_BlockUser() { types.EventTypeBlockUser, sdk.NewAttribute(types.AttributeKeyUserBlockBlocker, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), sdk.NewAttribute(types.AttributeKeyUserBlockBlocked, "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns"), - sdk.NewAttribute(types.AttributeKeySubspace, "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"), + sdk.NewAttribute(types.AttributeKeySubspace, "1"), sdk.NewAttribute(types.AttributeKeyUserBlockReason, "reason"), ), }, @@ -67,7 +67,7 @@ func (suite *KeeperTestSuite) TestMsgServer_BlockUser() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, ), } suite.Require().Equal(expected, suite.k.GetAllUsersBlocks(ctx)) @@ -113,8 +113,8 @@ func (suite *KeeperTestSuite) TestMsgServer_UnblockUser() { name: "invalid block returns error", msg: types.NewMsgUnblockUser( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "subspace", + "cosmos1cjf97gpzwmaf30", + 0, ), shouldErr: true, }, @@ -125,7 +125,7 @@ func (suite *KeeperTestSuite) TestMsgServer_UnblockUser() { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -134,7 +134,7 @@ func (suite *KeeperTestSuite) TestMsgServer_UnblockUser() { msg: types.NewMsgUnblockUser( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, ), shouldErr: false, expEvents: sdk.Events{ @@ -142,7 +142,7 @@ func (suite *KeeperTestSuite) TestMsgServer_UnblockUser() { types.EventTypeUnblockUser, sdk.NewAttribute(types.AttributeKeyUserBlockBlocker, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), sdk.NewAttribute(types.AttributeKeyUserBlockBlocked, "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns"), - sdk.NewAttribute(types.AttributeKeySubspace, "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"), + sdk.NewAttribute(types.AttributeKeySubspace, "1"), ), }, check: func(ctx sdk.Context) { diff --git a/x/profiles/keeper/msg_server_dtag_transfers_test.go b/x/profiles/keeper/msg_server_dtag_transfers_test.go index 58c5838dd2..ed9a6d7120 100644 --- a/x/profiles/keeper/msg_server_dtag_transfers_test.go +++ b/x/profiles/keeper/msg_server_dtag_transfers_test.go @@ -27,7 +27,7 @@ func (suite *KeeperTestSuite) TestMsgServer_RequestDTagTransfer() { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "This user has been blocked", - "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", + 1, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) diff --git a/x/profiles/keeper/msg_server_relationships.go b/x/profiles/keeper/msg_server_relationships.go index 9b71bfe4ce..89b3057e9c 100644 --- a/x/profiles/keeper/msg_server_relationships.go +++ b/x/profiles/keeper/msg_server_relationships.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "fmt" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -12,6 +13,11 @@ import ( func (k msgServer) CreateRelationship(goCtx context.Context, msg *types.MsgCreateRelationship) (*types.MsgCreateRelationshipResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + // Check if the subspace exists + if !k.HasSubspace(ctx, msg.Subspace) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.Subspace) + } + // Check if the receiver has blocked the sender before if k.HasUserBlocked(ctx, msg.Receiver, msg.Sender, msg.Subspace) { return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "The user with address %s has blocked you", msg.Receiver) @@ -27,7 +33,7 @@ func (k msgServer) CreateRelationship(goCtx context.Context, msg *types.MsgCreat types.EventTypeRelationshipCreated, sdk.NewAttribute(types.AttributeRelationshipSender, msg.Sender), sdk.NewAttribute(types.AttributeRelationshipReceiver, msg.Receiver), - sdk.NewAttribute(types.AttributeRelationshipSubspace, msg.Subspace), + sdk.NewAttribute(types.AttributeRelationshipSubspace, fmt.Sprintf("%d", msg.Subspace)), )) return &types.MsgCreateRelationshipResponse{}, nil @@ -45,7 +51,7 @@ func (k msgServer) DeleteRelationship(goCtx context.Context, msg *types.MsgDelet types.EventTypeRelationshipsDeleted, sdk.NewAttribute(types.AttributeRelationshipSender, msg.User), sdk.NewAttribute(types.AttributeRelationshipReceiver, msg.Counterparty), - sdk.NewAttribute(types.AttributeRelationshipSubspace, msg.Subspace), + sdk.NewAttribute(types.AttributeRelationshipSubspace, fmt.Sprintf("%d", msg.Subspace)), )) return &types.MsgDeleteRelationshipResponse{}, nil diff --git a/x/profiles/keeper/msg_server_relationships_test.go b/x/profiles/keeper/msg_server_relationships_test.go index 0f46b48277..bac3c134f8 100644 --- a/x/profiles/keeper/msg_server_relationships_test.go +++ b/x/profiles/keeper/msg_server_relationships_test.go @@ -1,8 +1,12 @@ package keeper_test import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" + subspacestypes "github.com/desmos-labs/desmos/v2/x/subspaces/types" + "github.com/desmos-labs/desmos/v2/testutil" "github.com/desmos-labs/desmos/v2/x/profiles/keeper" @@ -25,7 +29,7 @@ func (suite *KeeperTestSuite) TestMsgServer_CreateRelationship() { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "tc", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocker))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(block.Blocked))) @@ -34,7 +38,7 @@ func (suite *KeeperTestSuite) TestMsgServer_CreateRelationship() { msg: types.NewMsgCreateRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), shouldErr: true, }, @@ -44,7 +48,7 @@ func (suite *KeeperTestSuite) TestMsgServer_CreateRelationship() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Creator))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr(relationship.Recipient))) @@ -53,20 +57,29 @@ func (suite *KeeperTestSuite) TestMsgServer_CreateRelationship() { msg: types.NewMsgCreateRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), shouldErr: true, }, { name: "new relationship is stored correctly", store: func(ctx sdk.Context) { + suite.sk.SaveSubspace(ctx, subspacestypes.NewSubspace( + 0, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"))) suite.Require().NoError(suite.k.StoreProfile(ctx, testutil.ProfileFromAddr("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns"))) }, msg: types.NewMsgCreateRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), shouldErr: false, expEvents: sdk.Events{ @@ -74,7 +87,7 @@ func (suite *KeeperTestSuite) TestMsgServer_CreateRelationship() { types.EventTypeRelationshipCreated, sdk.NewAttribute(types.AttributeRelationshipSender, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), sdk.NewAttribute(types.AttributeRelationshipReceiver, "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns"), - sdk.NewAttribute(types.AttributeRelationshipSubspace, "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"), + sdk.NewAttribute(types.AttributeRelationshipSubspace, "0"), ), }, check: func(ctx sdk.Context) { @@ -82,7 +95,7 @@ func (suite *KeeperTestSuite) TestMsgServer_CreateRelationship() { types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ), } suite.Require().Equal(expected, suite.k.GetAllRelationships(ctx)) @@ -129,7 +142,7 @@ func (suite *KeeperTestSuite) TestMsgServer_DeleteRelationship() { msg: types.NewMsgDeleteRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "other_subspace", + 2, ), shouldErr: true, }, @@ -140,7 +153,7 @@ func (suite *KeeperTestSuite) TestMsgServer_DeleteRelationship() { relationship := types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 1, ) store.Set( types.RelationshipsStoreKey(relationship.Creator, relationship.Subspace, relationship.Recipient), @@ -150,7 +163,7 @@ func (suite *KeeperTestSuite) TestMsgServer_DeleteRelationship() { msg: types.NewMsgDeleteRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x", - "subspace", + 1, ), shouldErr: false, expEvents: sdk.Events{ @@ -158,7 +171,7 @@ func (suite *KeeperTestSuite) TestMsgServer_DeleteRelationship() { types.EventTypeRelationshipsDeleted, sdk.NewAttribute(types.AttributeRelationshipSender, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), sdk.NewAttribute(types.AttributeRelationshipReceiver, "cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x"), - sdk.NewAttribute(types.AttributeRelationshipSubspace, "subspace"), + sdk.NewAttribute(types.AttributeRelationshipSubspace, "1"), ), }, check: func(ctx sdk.Context) { diff --git a/x/profiles/legacy/v230/keys.go b/x/profiles/legacy/v230/keys.go new file mode 100644 index 0000000000..fa90f2fe84 --- /dev/null +++ b/x/profiles/legacy/v230/keys.go @@ -0,0 +1,40 @@ +package v230 + +var ( + RelationshipsStorePrefix = []byte("relationships") + UsersBlocksStorePrefix = []byte("users_blocks") +) + +// UserRelationshipsPrefix returns the prefix used to store all relationships created +// by the user with the given address +func UserRelationshipsPrefix(user string) []byte { + return append(RelationshipsStorePrefix, []byte(user)...) +} + +// UserRelationshipsSubspacePrefix returns the prefix used to store all the relationships created by the user +// with the given address for the subspace having the given id +func UserRelationshipsSubspacePrefix(user, subspace string) []byte { + return append(UserRelationshipsPrefix(user), []byte(subspace)...) +} + +// RelationshipsStoreKey returns the store key used to store the relationships containing the given data +func RelationshipsStoreKey(user, subspace, recipient string) []byte { + return append(UserRelationshipsSubspacePrefix(user, subspace), []byte(recipient)...) +} + +// BlockerPrefix returns the store prefix used to store the blocks created by the given blocker +func BlockerPrefix(blocker string) []byte { + return append(UsersBlocksStorePrefix, []byte(blocker)...) +} + +// BlockerSubspacePrefix returns the store prefix used to store the blocks that the given blocker +// has created inside the specified subspace +func BlockerSubspacePrefix(blocker string, subspace string) []byte { + return append(BlockerPrefix(blocker), []byte(subspace)...) +} + +// UserBlockStoreKey returns the store key used to save the block made by the given blocker, +// inside the specified subspace and towards the given blocked user +func UserBlockStoreKey(blocker string, subspace string, blockedUser string) []byte { + return append(BlockerSubspacePrefix(blocker, subspace), []byte(blockedUser)...) +} diff --git a/x/profiles/legacy/v230/models_chain_links.pb.go b/x/profiles/legacy/v230/models_chain_links.pb.go index 252a1eedc3..e42624572b 100644 --- a/x/profiles/legacy/v230/models_chain_links.pb.go +++ b/x/profiles/legacy/v230/models_chain_links.pb.go @@ -124,7 +124,8 @@ type Proof struct { PubKey *types.Any `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty" yaml:"pub_key"` // Signature represents the hex-encoded signature of the PlainText value Signature string `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" yaml:"signature"` - // PlainText represents the hex-encoded value signed in order to produce the Signature + // PlainText represents the hex-encoded value signed in order to produce the + // Signature PlainText string `protobuf:"bytes,3,opt,name=plain_text,json=plainText,proto3" json:"plain_text,omitempty" yaml:"plain_text"` } @@ -246,7 +247,8 @@ var xxx_messageInfo_Base58Address proto.InternalMessageInfo type HexAddress struct { // Value represents the hex address value Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty" yaml:"value"` - // Prefix represents the optional prefix used during address encoding (e.g. 0x) + // Prefix represents the optional prefix used during address encoding (e.g. + // 0x) Prefix string `protobuf:"bytes,2,opt,name=prefix,proto3" json:"prefix,omitempty" yaml:"prefix"` } diff --git a/x/profiles/legacy/v230/models_relationships.pb.go b/x/profiles/legacy/v230/models_relationships.pb.go new file mode 100644 index 0000000000..e1aefb5f40 --- /dev/null +++ b/x/profiles/legacy/v230/models_relationships.pb.go @@ -0,0 +1,832 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/profiles/legacy/v230/models_relationships.proto + +package v230 + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-proto" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Relationship is the struct of a relationship. +// It represent the concept of "follow" of traditional social networks. +type Relationship struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty" yaml:"creator"` + Recipient string `protobuf:"bytes,2,opt,name=recipient,proto3" json:"recipient,omitempty" yaml:"recipient"` + Subspace string `protobuf:"bytes,3,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` +} + +func (m *Relationship) Reset() { *m = Relationship{} } +func (m *Relationship) String() string { return proto.CompactTextString(m) } +func (*Relationship) ProtoMessage() {} +func (*Relationship) Descriptor() ([]byte, []int) { + return fileDescriptor_4929e4628d8fdc04, []int{0} +} +func (m *Relationship) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Relationship) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Relationship.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Relationship) XXX_Merge(src proto.Message) { + xxx_messageInfo_Relationship.Merge(m, src) +} +func (m *Relationship) XXX_Size() int { + return m.Size() +} +func (m *Relationship) XXX_DiscardUnknown() { + xxx_messageInfo_Relationship.DiscardUnknown(m) +} + +var xxx_messageInfo_Relationship proto.InternalMessageInfo + +func (m *Relationship) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *Relationship) GetRecipient() string { + if m != nil { + return m.Recipient + } + return "" +} + +func (m *Relationship) GetSubspace() string { + if m != nil { + return m.Subspace + } + return "" +} + +// UserBlock represents the fact that the Blocker has blocked the given Blocked +// user. +type UserBlock struct { + // Blocker represents the address of the user blocking another one + Blocker string `protobuf:"bytes,1,opt,name=blocker,proto3" json:"blocker,omitempty" yaml:"blocker"` + // Blocked represents the address of the blocked user + Blocked string `protobuf:"bytes,2,opt,name=blocked,proto3" json:"blocked,omitempty" yaml:"blocked"` + // Reason represents the optional reason the user has been blocked for. + Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty" yaml:"reason"` + // Subspace contains the ID of the subspace inside which the user should be + // blocked + Subspace string `protobuf:"bytes,4,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` +} + +func (m *UserBlock) Reset() { *m = UserBlock{} } +func (m *UserBlock) String() string { return proto.CompactTextString(m) } +func (*UserBlock) ProtoMessage() {} +func (*UserBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_4929e4628d8fdc04, []int{1} +} +func (m *UserBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UserBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UserBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *UserBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_UserBlock.Merge(m, src) +} +func (m *UserBlock) XXX_Size() int { + return m.Size() +} +func (m *UserBlock) XXX_DiscardUnknown() { + xxx_messageInfo_UserBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_UserBlock proto.InternalMessageInfo + +func (m *UserBlock) GetBlocker() string { + if m != nil { + return m.Blocker + } + return "" +} + +func (m *UserBlock) GetBlocked() string { + if m != nil { + return m.Blocked + } + return "" +} + +func (m *UserBlock) GetReason() string { + if m != nil { + return m.Reason + } + return "" +} + +func (m *UserBlock) GetSubspace() string { + if m != nil { + return m.Subspace + } + return "" +} + +func init() { + proto.RegisterType((*Relationship)(nil), "desmos.profiles.legacy.v230.Relationship") + proto.RegisterType((*UserBlock)(nil), "desmos.profiles.legacy.v230.UserBlock") +} + +func init() { + proto.RegisterFile("desmos/profiles/legacy/v230/models_relationships.proto", fileDescriptor_4929e4628d8fdc04) +} + +var fileDescriptor_4929e4628d8fdc04 = []byte{ + // 387 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xbd, 0x4e, 0xeb, 0x30, + 0x18, 0x86, 0xeb, 0x73, 0x8e, 0x7a, 0xda, 0xe8, 0xfc, 0x40, 0xe8, 0x50, 0x8a, 0x94, 0x20, 0x4f, + 0x20, 0x41, 0x8c, 0x5a, 0x09, 0xa4, 0x8e, 0xbd, 0x03, 0x22, 0xb1, 0xb0, 0x54, 0x4e, 0xe2, 0xa6, + 0x11, 0x4e, 0xbe, 0xc8, 0x4e, 0x2b, 0x7a, 0x17, 0x8c, 0x8c, 0xdd, 0xb9, 0x11, 0x16, 0xa4, 0x8e, + 0x4c, 0x11, 0x6a, 0x17, 0xe6, 0x5c, 0x01, 0x4a, 0x9c, 0xb4, 0xfc, 0x74, 0x61, 0xfb, 0x9c, 0xf7, + 0x79, 0x92, 0xf7, 0x53, 0xac, 0x9d, 0x7b, 0x4c, 0x86, 0x20, 0x49, 0x2c, 0x60, 0x14, 0x70, 0x26, + 0x09, 0x67, 0x3e, 0x75, 0x67, 0x64, 0xda, 0xed, 0x9d, 0x91, 0x10, 0x3c, 0xc6, 0xe5, 0x50, 0x30, + 0x4e, 0x93, 0x00, 0x22, 0x39, 0x0e, 0x62, 0x69, 0xc5, 0x02, 0x12, 0xd0, 0x0f, 0x94, 0x67, 0x55, + 0x9e, 0xa5, 0x3c, 0x2b, 0xf7, 0x3a, 0x2d, 0x1f, 0x7c, 0x28, 0x38, 0x92, 0x4f, 0x4a, 0xe9, 0xec, + 0xfb, 0x00, 0x3e, 0x67, 0xa4, 0x38, 0x39, 0x93, 0x11, 0xa1, 0xd1, 0xac, 0x8c, 0xcc, 0xcf, 0x51, + 0x12, 0x84, 0x4c, 0x26, 0x34, 0x8c, 0x2b, 0xd7, 0x85, 0xfc, 0x73, 0x43, 0xf5, 0x52, 0x75, 0x50, + 0x11, 0x7e, 0x40, 0xda, 0x1f, 0xfb, 0x5d, 0x43, 0xfd, 0x44, 0xfb, 0xed, 0x0a, 0x46, 0x13, 0x10, + 0x6d, 0x74, 0x88, 0x8e, 0x9a, 0x03, 0x3d, 0x4b, 0xcd, 0x7f, 0x33, 0x1a, 0xf2, 0x3e, 0x2e, 0x03, + 0x6c, 0x57, 0x88, 0xde, 0xd5, 0x9a, 0x82, 0xb9, 0x41, 0x1c, 0xb0, 0x28, 0x69, 0xff, 0x28, 0xf8, + 0x56, 0x96, 0x9a, 0x3b, 0x8a, 0x5f, 0x47, 0xd8, 0xde, 0x60, 0x3a, 0xd1, 0x1a, 0x72, 0xe2, 0xc8, + 0x98, 0xba, 0xac, 0xfd, 0xb3, 0x50, 0xf6, 0xb2, 0xd4, 0xfc, 0xaf, 0x94, 0x2a, 0xc1, 0xf6, 0x1a, + 0xea, 0x37, 0xee, 0xe7, 0x26, 0x7a, 0x9d, 0x9b, 0x08, 0x3f, 0x21, 0xad, 0x79, 0x25, 0x99, 0x18, + 0x70, 0x70, 0x6f, 0xf2, 0xaa, 0x4e, 0x3e, 0xb0, 0x2d, 0x55, 0xcb, 0x00, 0xdb, 0x15, 0xb2, 0xa1, + 0xbd, 0xb2, 0xe8, 0x17, 0xda, 0x5b, 0xd3, 0x9e, 0x7e, 0xac, 0xd5, 0x05, 0xa3, 0x12, 0xa2, 0xb2, + 0xe2, 0x6e, 0x96, 0x9a, 0x7f, 0xab, 0xad, 0xf2, 0xe7, 0xd8, 0x2e, 0x81, 0x0f, 0xfb, 0xfc, 0xfa, + 0xd6, 0x3e, 0x83, 0xcb, 0xc7, 0xa5, 0x81, 0x16, 0x4b, 0x03, 0xbd, 0x2c, 0x0d, 0x74, 0xb7, 0x32, + 0x6a, 0x8b, 0x95, 0x51, 0x7b, 0x5e, 0x19, 0xb5, 0xeb, 0x0b, 0x3f, 0x48, 0xc6, 0x13, 0xc7, 0x72, + 0x21, 0x24, 0xea, 0xb2, 0x9c, 0x72, 0xea, 0xc8, 0x72, 0x26, 0xd3, 0x2e, 0xb9, 0xdd, 0x7a, 0xeb, + 0x9c, 0x7a, 0xf1, 0x5f, 0x7b, 0x6f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x95, 0x70, 0xc1, 0x81, 0x9b, + 0x02, 0x00, 0x00, +} + +func (this *Relationship) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Relationship) + if !ok { + that2, ok := that.(Relationship) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Creator != that1.Creator { + return false + } + if this.Recipient != that1.Recipient { + return false + } + if this.Subspace != that1.Subspace { + return false + } + return true +} +func (this *UserBlock) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*UserBlock) + if !ok { + that2, ok := that.(UserBlock) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Blocker != that1.Blocker { + return false + } + if this.Blocked != that1.Blocked { + return false + } + if this.Reason != that1.Reason { + return false + } + if this.Subspace != that1.Subspace { + return false + } + return true +} +func (m *Relationship) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Relationship) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Relationship) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Subspace) > 0 { + i -= len(m.Subspace) + copy(dAtA[i:], m.Subspace) + i = encodeVarintModelsRelationships(dAtA, i, uint64(len(m.Subspace))) + i-- + dAtA[i] = 0x1a + } + if len(m.Recipient) > 0 { + i -= len(m.Recipient) + copy(dAtA[i:], m.Recipient) + i = encodeVarintModelsRelationships(dAtA, i, uint64(len(m.Recipient))) + i-- + dAtA[i] = 0x12 + } + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintModelsRelationships(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *UserBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UserBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UserBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Subspace) > 0 { + i -= len(m.Subspace) + copy(dAtA[i:], m.Subspace) + i = encodeVarintModelsRelationships(dAtA, i, uint64(len(m.Subspace))) + i-- + dAtA[i] = 0x22 + } + if len(m.Reason) > 0 { + i -= len(m.Reason) + copy(dAtA[i:], m.Reason) + i = encodeVarintModelsRelationships(dAtA, i, uint64(len(m.Reason))) + i-- + dAtA[i] = 0x1a + } + if len(m.Blocked) > 0 { + i -= len(m.Blocked) + copy(dAtA[i:], m.Blocked) + i = encodeVarintModelsRelationships(dAtA, i, uint64(len(m.Blocked))) + i-- + dAtA[i] = 0x12 + } + if len(m.Blocker) > 0 { + i -= len(m.Blocker) + copy(dAtA[i:], m.Blocker) + i = encodeVarintModelsRelationships(dAtA, i, uint64(len(m.Blocker))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintModelsRelationships(dAtA []byte, offset int, v uint64) int { + offset -= sovModelsRelationships(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Relationship) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovModelsRelationships(uint64(l)) + } + l = len(m.Recipient) + if l > 0 { + n += 1 + l + sovModelsRelationships(uint64(l)) + } + l = len(m.Subspace) + if l > 0 { + n += 1 + l + sovModelsRelationships(uint64(l)) + } + return n +} + +func (m *UserBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Blocker) + if l > 0 { + n += 1 + l + sovModelsRelationships(uint64(l)) + } + l = len(m.Blocked) + if l > 0 { + n += 1 + l + sovModelsRelationships(uint64(l)) + } + l = len(m.Reason) + if l > 0 { + n += 1 + l + sovModelsRelationships(uint64(l)) + } + l = len(m.Subspace) + if l > 0 { + n += 1 + l + sovModelsRelationships(uint64(l)) + } + return n +} + +func sovModelsRelationships(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozModelsRelationships(x uint64) (n int) { + return sovModelsRelationships(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Relationship) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Relationship: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Relationship: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModelsRelationships + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModelsRelationships + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Recipient", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModelsRelationships + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModelsRelationships + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Recipient = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModelsRelationships + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModelsRelationships + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Subspace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipModelsRelationships(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModelsRelationships + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *UserBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UserBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UserBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Blocker", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModelsRelationships + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModelsRelationships + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Blocker = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Blocked", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModelsRelationships + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModelsRelationships + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Blocked = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Reason", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModelsRelationships + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModelsRelationships + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Reason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModelsRelationships + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModelsRelationships + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Subspace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipModelsRelationships(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModelsRelationships + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipModelsRelationships(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModelsRelationships + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthModelsRelationships + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupModelsRelationships + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthModelsRelationships + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthModelsRelationships = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowModelsRelationships = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupModelsRelationships = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/profiles/legacy/v300/store.go b/x/profiles/legacy/v300/store.go new file mode 100644 index 0000000000..96db74ad79 --- /dev/null +++ b/x/profiles/legacy/v300/store.go @@ -0,0 +1,125 @@ +package v300 + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + + subspacestypes "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + v230 "github.com/desmos-labs/desmos/v2/x/profiles/legacy/v230" + "github.com/desmos-labs/desmos/v2/x/profiles/types" +) + +// MigrateStore performs in-place store migrations from v2.3 to v3.0. +// The migration includes: +// +// - replace all relationship subspace id from string to uint64 +// - replace all user blocks subspace id from string to uint64 +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, cdc codec.BinaryCodec) error { + store := ctx.KVStore(storeKey) + + err := migrateUserBlocks(store, cdc) + if err != nil { + return err + } + + err = migrateRelationships(store, cdc) + if err != nil { + return err + } + + return nil +} + +// migrateUserBlocks migrates the user blocks stored to the new type, converting the subspace from string to uint64 +func migrateUserBlocks(store sdk.KVStore, cdc codec.BinaryCodec) error { + var values []v230.UserBlock + + userBlocksStore := prefix.NewStore(store, v230.UsersBlocksStorePrefix) + iterator := userBlocksStore.Iterator(nil, nil) + + for ; iterator.Valid(); iterator.Next() { + var block v230.UserBlock + err := cdc.Unmarshal(iterator.Value(), &block) + if err != nil { + return err + } + values = append(values, block) + } + + // Close the iterator + err := iterator.Close() + if err != nil { + return err + } + + for _, v230Block := range values { + // Delete the previous key + store.Delete(v230.UserBlockStoreKey(v230Block.Blocker, v230Block.Subspace, v230Block.Blocked)) + + // Get the subspace id + subspaceID, err := subspacestypes.ParseSubspaceID(v230Block.Subspace) + if err != nil { + return err + } + + // Serialize the block as the new type + v300Block := types.NewUserBlock(v230Block.Blocker, v230Block.Blocked, v230Block.Reason, subspaceID) + blockBz, err := cdc.Marshal(&v300Block) + if err != nil { + return err + } + + // Store the new value inside the store + store.Set(types.UserBlockStoreKey(v300Block.Blocker, v300Block.Subspace, v300Block.Blocked), blockBz) + } + + return nil +} + +// migrateRelationships migrates the relationships stored to the new type, converting the subspace from string to uint64 +func migrateRelationships(store sdk.KVStore, cdc codec.BinaryCodec) error { + var values []v230.Relationship + + relationshipsStore := prefix.NewStore(store, types.RelationshipsStorePrefix) + iterator := relationshipsStore.Iterator(nil, nil) + + for ; iterator.Valid(); iterator.Next() { + var relationship v230.Relationship + err := cdc.Unmarshal(iterator.Value(), &relationship) + if err != nil { + return err + } + values = append(values, relationship) + } + + // Close the iterator + err := iterator.Close() + if err != nil { + return err + } + + for _, v230Relationship := range values { + // Delete the previous key + store.Delete(v230.RelationshipsStoreKey(v230Relationship.Creator, v230Relationship.Subspace, v230Relationship.Recipient)) + + // Get the subspace id + subspaceID, err := subspacestypes.ParseSubspaceID(v230Relationship.Subspace) + if err != nil { + return err + } + + // Serialize the relationship as the new type + v300Relationship := types.NewRelationship(v230Relationship.Creator, v230Relationship.Recipient, subspaceID) + relationshipBz, err := cdc.Marshal(&v300Relationship) + if err != nil { + return err + } + + // Store the new relationship inside the store + store.Set(types.RelationshipsStoreKey(v300Relationship.Creator, v300Relationship.Subspace, v300Relationship.Recipient), relationshipBz) + } + + return nil +} diff --git a/x/profiles/legacy/v300/store_test.go b/x/profiles/legacy/v300/store_test.go new file mode 100644 index 0000000000..ea31c9c680 --- /dev/null +++ b/x/profiles/legacy/v300/store_test.go @@ -0,0 +1,95 @@ +package v300_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "github.com/desmos-labs/desmos/v2/app" + v230 "github.com/desmos-labs/desmos/v2/x/profiles/legacy/v230" + v300 "github.com/desmos-labs/desmos/v2/x/profiles/legacy/v300" + "github.com/desmos-labs/desmos/v2/x/profiles/types" +) + +func TestMigrateStore(t *testing.T) { + cdc, _ := app.MakeCodecs() + storeKey := sdk.NewKVStoreKey(types.StoreKey) + testCases := []struct { + name string + store func(ctx sdk.Context) + shouldErr bool + check func(ctx sdk.Context) + }{ + { + name: "valid data returns no error", + store: func(ctx sdk.Context) { + store := ctx.KVStore(storeKey) + + block := v230.UserBlock{ + Blocker: "blocker", + Blocked: "blocked", + Reason: "reason", + Subspace: "", + } + blockBz := cdc.MustMarshal(&block) + store.Set(v230.UserBlockStoreKey(block.Blocker, block.Subspace, block.Blocked), blockBz) + + relationship := v230.Relationship{ + Creator: "user", + Recipient: "recipient", + Subspace: "2", + } + relBz := cdc.MustMarshal(&relationship) + store.Set(append(types.RelationshipsStorePrefix, 0x01), relBz) + }, + shouldErr: false, + check: func(ctx sdk.Context) { + store := ctx.KVStore(storeKey) + + oldBlockKey := v230.UserBlockStoreKey("blocker", "", "blocked") + require.False(t, store.Has(oldBlockKey)) + + expectedBlock := types.NewUserBlock("blocker", "blocked", "reason", 0) + expectedBlockKey := types.UserBlockStoreKey(expectedBlock.Blocker, expectedBlock.Subspace, expectedBlock.Blocked) + require.True(t, store.Has(expectedBlockKey)) + + var storedBlock types.UserBlock + cdc.MustUnmarshal(store.Get(expectedBlockKey), &storedBlock) + require.Equal(t, expectedBlock, storedBlock) + + oldRelationshipKey := v230.RelationshipsStoreKey("user", "2", "recipient") + require.False(t, store.Has(oldRelationshipKey)) + + expectedRelationship := types.NewRelationship("user", "recipient", 2) + expectedRelationshipKey := types.RelationshipsStoreKey(expectedRelationship.Creator, expectedRelationship.Subspace, expectedRelationship.Recipient) + require.True(t, store.Has(expectedRelationshipKey)) + + var storedRelationship types.Relationship + cdc.MustUnmarshal(store.Get(expectedRelationshipKey), &storedRelationship) + require.Equal(t, expectedRelationship, storedRelationship) + }, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + ctx := testutil.DefaultContext(storeKey, sdk.NewTransientStoreKey("test")) + if tc.store != nil { + tc.store(ctx) + } + + err := v300.MigrateStore(ctx, storeKey, cdc) + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} diff --git a/x/profiles/module.go b/x/profiles/module.go index 6a0697178e..381589c80a 100644 --- a/x/profiles/module.go +++ b/x/profiles/module.go @@ -28,7 +28,7 @@ import ( ) const ( - consensusVersion = 4 + consensusVersion = 5 ) // type check to ensure the interface is properly implemented @@ -98,6 +98,7 @@ func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) type AppModule struct { AppModuleBasic keeper keeper.Keeper + sk keeper.SubspacesKeeper ak authkeeper.AccountKeeper bk bankkeeper.Keeper } @@ -120,16 +121,23 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err != nil { panic(err) } + err = cfg.RegisterMigration(types.ModuleName, 4, m.Migrate4to5) + if err != nil { + panic(err) + } } // NewAppModule creates a new AppModule Object func NewAppModule( - cdc codec.Codec, legacyAmino *codec.LegacyAmino, k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, + cdc codec.Codec, legacyAmino *codec.LegacyAmino, + k keeper.Keeper, sk keeper.SubspacesKeeper, + ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, ) AppModule { return AppModule{ AppModuleBasic: AppModuleBasic{cdc: cdc, legacyAmino: legacyAmino}, keeper: k, ak: ak, + sk: sk, bk: bk, } } @@ -222,5 +230,5 @@ func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { // WeightedOperations returns the all the profiles module operations with their respective weights. func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations(simState.AppParams, simState.Cdc, am.keeper, am.ak, am.bk) + return simulation.WeightedOperations(simState.AppParams, simState.Cdc, am.keeper, am.sk, am.ak, am.bk) } diff --git a/x/profiles/simulation/decoder.go b/x/profiles/simulation/decoder.go index 5aa1685bf2..2ffc1c5cb2 100644 --- a/x/profiles/simulation/decoder.go +++ b/x/profiles/simulation/decoder.go @@ -32,14 +32,14 @@ func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string { cdc.MustUnmarshal(kvA.Value, &relationshipA) cdc.MustUnmarshal(kvB.Value, &relationshipB) return fmt.Sprintf("Relationships A: %s\nRelationships B: %s\n", - relationshipA, relationshipB) + &relationshipA, &relationshipB) case bytes.HasPrefix(kvA.Key, types.UsersBlocksStorePrefix): var userBlockA, userBlockB types.UserBlock cdc.MustUnmarshal(kvA.Value, &userBlockA) cdc.MustUnmarshal(kvB.Value, &userBlockB) return fmt.Sprintf("User block A: %s\nUser block B: %s\n", - userBlockA, userBlockB) + &userBlockA, &userBlockB) case bytes.HasPrefix(kvA.Key, types.ChainLinksPrefix): var chainLinkA, chainLinkB types.ChainLink diff --git a/x/profiles/simulation/decoder_test.go b/x/profiles/simulation/decoder_test.go index 5418918a19..36bb4be519 100644 --- a/x/profiles/simulation/decoder_test.go +++ b/x/profiles/simulation/decoder_test.go @@ -32,14 +32,14 @@ func TestDecodeStore(t *testing.T) { relationship := types.NewRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, ) userBlock := types.NewUserBlock( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, ) kvPairs := kv.Pairs{Pairs: []kv.Pair{ @@ -57,7 +57,7 @@ func TestDecodeStore(t *testing.T) { { Key: types.RelationshipsStoreKey( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", ), Value: cdc.MustMarshal(&relationship), @@ -65,7 +65,7 @@ func TestDecodeStore(t *testing.T) { { Key: types.UserBlockStoreKey( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 1, "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", ), Value: cdc.MustMarshal(&userBlock), @@ -78,8 +78,8 @@ func TestDecodeStore(t *testing.T) { }{ {"DTags", fmt.Sprintf("DTagAddressA: %s\nDTagAddressB: %s\n", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns")}, {"DTag transfer request", fmt.Sprintf("RequestA: %s\nRequestB: %s\n", request, request)}, - {"Relationship", fmt.Sprintf("Relationships A: %s\nRelationships B: %s\n", relationship, relationship)}, - {"User block", fmt.Sprintf("User block A: %s\nUser block B: %s\n", userBlock, userBlock)}, + {"Relationship", fmt.Sprintf("Relationships A: %s\nRelationships B: %s\n", &relationship, &relationship)}, + {"User block", fmt.Sprintf("User block A: %s\nUser block B: %s\n", &userBlock, &userBlock)}, {"other", ""}, } diff --git a/x/profiles/simulation/genesis.go b/x/profiles/simulation/genesis.go index 50b451bc0f..0301aee49f 100644 --- a/x/profiles/simulation/genesis.go +++ b/x/profiles/simulation/genesis.go @@ -5,6 +5,9 @@ package simulation import ( "fmt" + subspacessim "github.com/desmos-labs/desmos/v2/x/subspaces/simulation" + subspacestypes "github.com/desmos-labs/desmos/v2/x/subspaces/types" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -37,11 +40,17 @@ func RandomizedGenState(simsState *module.SimulationState) { } simsState.GenState[authtypes.ModuleName] = bz - // Create and set profiles state + // Create and set subspaces state + var subspacesState subspacestypes.GenesisState + err = simsState.Cdc.UnmarshalJSON(simsState.GenState[subspacestypes.ModuleName], &subspacesState) + if err != nil { + panic(err) + } + profileGenesis := types.NewGenesisState( randomDTagTransferRequests(profiles, simsState, simsState.Rand.Intn(profilesNumber)), - randomRelationships(profiles, simsState, simsState.Rand.Intn(profilesNumber)), - randomUsersBlocks(profiles, simsState, simsState.Rand.Intn(profilesNumber)), + randomRelationships(profiles, subspacesState.Subspaces, simsState, simsState.Rand.Intn(profilesNumber)), + randomUsersBlocks(profiles, subspacesState.Subspaces, simsState, simsState.Rand.Intn(profilesNumber)), types.NewParams( RandomNicknameParams(simsState.Rand), RandomDTagParams(simsState.Rand), @@ -136,7 +145,7 @@ func containsDTagTransferRequest(slice []types.DTagTransferRequest, request type // randomRelationships returns randomly generated genesis relationships and their associated users - IDs map func randomRelationships( - profiles []*types.Profile, simState *module.SimulationState, number int, + profiles []*types.Profile, subspaces []subspacestypes.GenesisSubspace, simState *module.SimulationState, number int, ) []types.Relationship { relationships := make([]types.Relationship, number) for index := 0; index < number; { @@ -148,10 +157,11 @@ func randomRelationships( continue } + subspace := subspacessim.RandomGenesisSubspace(simState.Rand, subspaces) relationship := types.NewRelationship( profile1.GetAddress().String(), profile2.GetAddress().String(), - RandomSubspace(simState.Rand), + subspace.Subspace.ID, ) if !containsRelationship(relationships, relationship) { @@ -178,7 +188,7 @@ func containsRelationship(slice []types.Relationship, relationship types.Relatio // randomUsersBlocks func randomUsersBlocks( - profiles []*types.Profile, simState *module.SimulationState, number int, + profiles []*types.Profile, subspaces []subspacestypes.GenesisSubspace, simState *module.SimulationState, number int, ) []types.UserBlock { usersBlocks := make([]types.UserBlock, number) for index := 0; index < number; { @@ -190,11 +200,12 @@ func randomUsersBlocks( continue } + subspace := subspacessim.RandomGenesisSubspace(simState.Rand, subspaces) block := types.NewUserBlock( profile1.GetAddress().String(), profile2.GetAddress().String(), "reason", - RandomSubspace(simState.Rand), + subspace.Subspace.ID, ) if !containsUserBlock(usersBlocks, block) { diff --git a/x/profiles/simulation/operations.go b/x/profiles/simulation/operations.go index 42ee9353f5..f1bef34629 100644 --- a/x/profiles/simulation/operations.go +++ b/x/profiles/simulation/operations.go @@ -35,7 +35,7 @@ const ( // WeightedOperations returns all the operations from the module with their respective weights func WeightedOperations( appParams simtypes.AppParams, cdc codec.JSONCodec, - k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, + k keeper.Keeper, sk keeper.SubspacesKeeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, ) sim.WeightedOperations { var weightMsgSaveProfile int appParams.GetOrGenerate(cdc, OpWeightMsgSaveProfile, &weightMsgSaveProfile, nil, @@ -134,7 +134,7 @@ func WeightedOperations( ), sim.NewWeightedOperation( weightMsgCreateRelationship, - SimulateMsgCreateRelationship(k, ak, bk), + SimulateMsgCreateRelationship(k, sk, ak, bk), ), sim.NewWeightedOperation( weightMsgDeleteRelationship, diff --git a/x/profiles/simulation/operations_relationships.go b/x/profiles/simulation/operations_relationships.go index 8afbebbcf4..5fec43a213 100644 --- a/x/profiles/simulation/operations_relationships.go +++ b/x/profiles/simulation/operations_relationships.go @@ -5,6 +5,8 @@ package simulation import ( "math/rand" + subspacessim "github.com/desmos-labs/desmos/v2/x/subspaces/simulation" + "github.com/desmos-labs/desmos/v2/testutil/simtesting" "github.com/desmos-labs/desmos/v2/x/profiles/keeper" @@ -21,14 +23,14 @@ import ( // SimulateMsgCreateRelationship tests and runs a single msg create relationships func SimulateMsgCreateRelationship( - k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, + k keeper.Keeper, sk keeper.SubspacesKeeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, ) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, ) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) { - acc, relationship, skip := randomRelationshipFields(r, ctx, accs, k) + acc, relationship, skip := randomRelationshipFields(r, ctx, accs, k, sk) if skip { return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgCreateRelationship"), nil, nil } @@ -45,7 +47,7 @@ func SimulateMsgCreateRelationship( // randomRelationshipFields returns random relationships fields func randomRelationshipFields( - r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, sk keeper.SubspacesKeeper, ) (simtypes.Account, types.Relationship, bool) { if len(accs) == 0 { return simtypes.Account{}, types.Relationship{}, true @@ -54,7 +56,9 @@ func randomRelationshipFields( // Get random accounts sender, _ := simtypes.RandomAcc(r, accs) receiver, _ := simtypes.RandomAcc(r, accs) - subspace := RandomSubspace(r) + + subspaces := sk.GetAllSubspaces(ctx) + subspace, _ := subspacessim.RandomSubspace(r, subspaces) // Skip if the send and receiver are equals if sender.Equals(receiver) { @@ -72,11 +76,11 @@ func randomRelationshipFields( } // Skip if the receiver has block the sender - if k.HasUserBlocked(ctx, receiver.Address.String(), sender.Address.String(), subspace) { + if k.HasUserBlocked(ctx, receiver.Address.String(), sender.Address.String(), subspace.ID) { return simtypes.Account{}, types.Relationship{}, true } - rel := types.NewRelationship(sender.Address.String(), receiver.Address.String(), subspace) + rel := types.NewRelationship(sender.Address.String(), receiver.Address.String(), subspace.ID) // Skip if relationships already exists relationships := k.GetUserRelationships(ctx, sender.Address.String()) @@ -117,9 +121,9 @@ func SimulateMsgDeleteRelationship( // randomDeleteRelationshipFields returns random delete relationships fields func randomDeleteRelationshipFields( r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, -) (user simtypes.Account, counterparty string, subspace string, skip bool) { +) (user simtypes.Account, counterparty string, subspace uint64, skip bool) { if len(accs) == 0 { - return simtypes.Account{}, "", "", true + return simtypes.Account{}, "", 0, true } // Get a random account @@ -138,7 +142,7 @@ func randomDeleteRelationshipFields( // Skip the test if the user has no relationships if len(outgoingRelationships) == 0 { - return simtypes.Account{}, "", "", true + return simtypes.Account{}, "", 0, true } // Get a random relationship diff --git a/x/profiles/simulation/operations_user_blocks.go b/x/profiles/simulation/operations_user_blocks.go index 23c322739b..2e2321551b 100644 --- a/x/profiles/simulation/operations_user_blocks.go +++ b/x/profiles/simulation/operations_user_blocks.go @@ -36,7 +36,7 @@ func SimulateMsgBlockUser( acc.Address.String(), blocked.String(), "reason", - "", + 0, ) err = simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{acc.PrivKey}) if err != nil { @@ -98,7 +98,7 @@ func SimulateMsgUnblockUser( msg := types.NewMsgUnblockUser( acc.Address.String(), userBlock.Blocked, - "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", + 0, ) err = simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{acc.PrivKey}) if err != nil { diff --git a/x/profiles/types/genesis.go b/x/profiles/types/genesis.go index 3a9124f2b7..93708478da 100644 --- a/x/profiles/types/genesis.go +++ b/x/profiles/types/genesis.go @@ -42,9 +42,9 @@ func ValidateGenesis(data *GenesisState) error { } } - for _, rel := range data.Relationships { + for i, rel := range data.Relationships { if containDuplicates(data.Relationships, rel) { - return fmt.Errorf("duplicated relationship: %s", rel) + return fmt.Errorf("duplicated relationship: %s", &data.Relationships[i]) } err = rel.Validate() diff --git a/x/profiles/types/genesis_test.go b/x/profiles/types/genesis_test.go index 09b99bf36e..1ddb163b10 100644 --- a/x/profiles/types/genesis_test.go +++ b/x/profiles/types/genesis_test.go @@ -68,12 +68,12 @@ func TestValidateGenesis(t *testing.T) { types.NewRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "", - "", + 0, ), types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "subspace", + "cosmos1y54exmx84cqtasv", + 1, ), }, []types.UserBlock{ @@ -81,13 +81,13 @@ func TestValidateGenesis(t *testing.T) { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "", + 0, ), types.NewUserBlock( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "reason", - "", + 0, ), }, types.DefaultParams(), @@ -105,12 +105,12 @@ func TestValidateGenesis(t *testing.T) { types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "", + 0, ), types.NewRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "", + 0, ), }, []types.UserBlock{ @@ -118,7 +118,7 @@ func TestValidateGenesis(t *testing.T) { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "", "reason", - "", + 0, ), }, types.DefaultParams(), @@ -136,12 +136,12 @@ func TestValidateGenesis(t *testing.T) { types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "", + 0, ), types.NewRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "", + 0, ), }, []types.UserBlock{ @@ -149,7 +149,7 @@ func TestValidateGenesis(t *testing.T) { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "reason", - "", + 0, ), }, types.DefaultParams(), @@ -228,12 +228,12 @@ func TestValidateGenesis(t *testing.T) { types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "", + 0, ), types.NewRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "", + 0, ), }, []types.UserBlock{ @@ -241,13 +241,13 @@ func TestValidateGenesis(t *testing.T) { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "reason", - "", + 0, ), types.NewUserBlock( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "reason", - "", + 0, ), }, types.DefaultParams(), diff --git a/x/profiles/types/keys.go b/x/profiles/types/keys.go index b9c6365135..e09cffc2fb 100644 --- a/x/profiles/types/keys.go +++ b/x/profiles/types/keys.go @@ -1,6 +1,10 @@ package types -import "strings" +import ( + "strings" + + subspacestypes "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) // DONTCOVER @@ -71,12 +75,12 @@ func UserRelationshipsPrefix(user string) []byte { // UserRelationshipsSubspacePrefix returns the prefix used to store all the relationships created by the user // with the given address for the subspace having the given id -func UserRelationshipsSubspacePrefix(user, subspace string) []byte { - return append(UserRelationshipsPrefix(user), []byte(subspace)...) +func UserRelationshipsSubspacePrefix(user string, subspace uint64) []byte { + return append(UserRelationshipsPrefix(user), subspacestypes.GetSubspaceIDBytes(subspace)...) } // RelationshipsStoreKey returns the store key used to store the relationships containing the given data -func RelationshipsStoreKey(user, subspace, recipient string) []byte { +func RelationshipsStoreKey(user string, subspace uint64, recipient string) []byte { return append(UserRelationshipsSubspacePrefix(user, subspace), []byte(recipient)...) } @@ -87,13 +91,13 @@ func BlockerPrefix(blocker string) []byte { // BlockerSubspacePrefix returns the store prefix used to store the blocks that the given blocker // has created inside the specified subspace -func BlockerSubspacePrefix(blocker string, subspace string) []byte { - return append(BlockerPrefix(blocker), []byte(subspace)...) +func BlockerSubspacePrefix(blocker string, subspace uint64) []byte { + return append(BlockerPrefix(blocker), subspacestypes.GetSubspaceIDBytes(subspace)...) } // UserBlockStoreKey returns the store key used to save the block made by the given blocker, // inside the specified subspace and towards the given blocked user -func UserBlockStoreKey(blocker string, subspace string, blockedUser string) []byte { +func UserBlockStoreKey(blocker string, subspace uint64, blockedUser string) []byte { return append(BlockerSubspacePrefix(blocker, subspace), []byte(blockedUser)...) } diff --git a/x/profiles/types/models_relationships.go b/x/profiles/types/models_relationships.go index 05a816ace9..283b4dd023 100644 --- a/x/profiles/types/models_relationships.go +++ b/x/profiles/types/models_relationships.go @@ -8,15 +8,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// IsValidSubspace tell whether the given subspace ID is valid or not. -// NOTE: Currently we only support the empty subspace which identifies the generic Desmos subspace that can be used -// to block users on every subspace -func IsValidSubspace(subspace string) bool { - return subspace == "" -} - // NewRelationship returns a new relationships with the given recipient and subspace -func NewRelationship(creator string, recipient string, subspace string) Relationship { +func NewRelationship(creator string, recipient string, subspace uint64) Relationship { return Relationship{ Creator: creator, Recipient: recipient, @@ -40,10 +33,6 @@ func (r Relationship) Validate() error { return fmt.Errorf("creator and recipient cannot be the same user") } - if !IsValidSubspace(r.Subspace) { - return fmt.Errorf("invalid subspace") - } - return nil } @@ -64,7 +53,7 @@ func MustUnmarshalRelationship(cdc codec.BinaryCodec, bz []byte) Relationship { // NewUserBlock returns a new object representing the fact that one user has blocked another one // for a specific reason on the given subspace. -func NewUserBlock(blocker, blocked string, reason, subspace string) UserBlock { +func NewUserBlock(blocker, blocked string, reason string, subspace uint64) UserBlock { return UserBlock{ Blocker: blocker, Blocked: blocked, @@ -87,10 +76,6 @@ func (ub UserBlock) Validate() error { return fmt.Errorf("blocker and blocked addresses cannot be equals") } - if !IsValidSubspace(ub.Subspace) { - return fmt.Errorf("invalid subspace") - } - return nil } diff --git a/x/profiles/types/models_relationships.pb.go b/x/profiles/types/models_relationships.pb.go index ec69626c94..e57a210789 100644 --- a/x/profiles/types/models_relationships.pb.go +++ b/x/profiles/types/models_relationships.pb.go @@ -31,7 +31,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type Relationship struct { Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty" yaml:"creator"` Recipient string `protobuf:"bytes,2,opt,name=recipient,proto3" json:"recipient,omitempty" yaml:"recipient"` - Subspace string `protobuf:"bytes,3,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` + Subspace uint64 `protobuf:"varint,3,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` } func (m *Relationship) Reset() { *m = Relationship{} } @@ -81,11 +81,11 @@ func (m *Relationship) GetRecipient() string { return "" } -func (m *Relationship) GetSubspace() string { +func (m *Relationship) GetSubspace() uint64 { if m != nil { return m.Subspace } - return "" + return 0 } // UserBlock represents the fact that the Blocker has blocked the given Blocked @@ -99,7 +99,7 @@ type UserBlock struct { Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty" yaml:"reason"` // Subspace contains the ID of the subspace inside which the user should be // blocked - Subspace string `protobuf:"bytes,4,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` + Subspace uint64 `protobuf:"varint,4,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` } func (m *UserBlock) Reset() { *m = UserBlock{} } @@ -156,11 +156,11 @@ func (m *UserBlock) GetReason() string { return "" } -func (m *UserBlock) GetSubspace() string { +func (m *UserBlock) GetSubspace() uint64 { if m != nil { return m.Subspace } - return "" + return 0 } func init() { @@ -173,32 +173,32 @@ func init() { } var fileDescriptor_47c7d48489f1a7d0 = []byte{ - // 395 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xbf, 0x4e, 0xeb, 0x30, - 0x18, 0xc5, 0xeb, 0x7b, 0xaf, 0x7a, 0xdb, 0xe8, 0xfe, 0x81, 0x50, 0x89, 0xd2, 0x21, 0x41, 0x9e, - 0x40, 0x82, 0x98, 0x96, 0xad, 0x63, 0x57, 0xb6, 0x48, 0x2c, 0x2c, 0x95, 0x93, 0xb8, 0xa9, 0x55, - 0x27, 0x8e, 0x6c, 0xb7, 0xa2, 0x6f, 0xc1, 0xc8, 0xd8, 0x9d, 0x17, 0x61, 0x41, 0xea, 0xc8, 0x14, - 0xa1, 0x76, 0x61, 0xce, 0x13, 0xa0, 0x24, 0x4e, 0xcb, 0x3f, 0x09, 0xb1, 0x7d, 0x5f, 0xce, 0xef, - 0xc4, 0xe7, 0xe8, 0x33, 0x7a, 0x01, 0x91, 0x11, 0x97, 0x28, 0x11, 0x7c, 0x44, 0x19, 0x91, 0x68, - 0xd6, 0xf5, 0x88, 0xc2, 0x5d, 0x14, 0xf1, 0x80, 0x30, 0x39, 0x14, 0x84, 0x61, 0x45, 0x79, 0x2c, - 0xc7, 0x34, 0x91, 0x4e, 0x22, 0xb8, 0xe2, 0xe6, 0x7e, 0xe9, 0x71, 0x2a, 0x8f, 0xa3, 0x3d, 0x9d, - 0x56, 0xc8, 0x43, 0x5e, 0x30, 0x28, 0x9f, 0x4a, 0xbc, 0x73, 0x10, 0x72, 0x1e, 0x32, 0x82, 0x8a, - 0xcd, 0x9b, 0x8e, 0x10, 0x8e, 0xe7, 0x5a, 0xb2, 0xdf, 0x4b, 0x8a, 0x46, 0x44, 0x2a, 0x1c, 0x25, - 0x95, 0xd7, 0xe7, 0xf9, 0x53, 0xc3, 0xf2, 0xa7, 0xe5, 0xa2, 0xa5, 0xb3, 0x2f, 0x92, 0xfb, 0x63, - 0x4c, 0xe3, 0x21, 0xa3, 0xf1, 0x44, 0x3b, 0xe0, 0x1d, 0x30, 0xfe, 0xb8, 0xaf, 0xfa, 0x98, 0x27, - 0xc6, 0x6f, 0x5f, 0x10, 0xac, 0xb8, 0x68, 0x83, 0x43, 0x70, 0xd4, 0x1c, 0x98, 0x59, 0x6a, 0xff, - 0x9b, 0xe3, 0x88, 0xf5, 0xa1, 0x16, 0xa0, 0x5b, 0x21, 0x66, 0xcf, 0x68, 0x0a, 0xe2, 0xd3, 0x84, - 0x92, 0x58, 0xb5, 0x7f, 0x14, 0x7c, 0x2b, 0x4b, 0xed, 0x9d, 0x92, 0xdf, 0x48, 0xd0, 0xdd, 0x62, - 0x26, 0x32, 0x1a, 0x72, 0xea, 0xc9, 0x04, 0xfb, 0xa4, 0xfd, 0xb3, 0xb0, 0xec, 0x65, 0xa9, 0xfd, - 0xbf, 0xb4, 0x54, 0x0a, 0x74, 0x37, 0x50, 0xbf, 0x71, 0xbb, 0xb0, 0xc1, 0xf3, 0xc2, 0x06, 0xf0, - 0x01, 0x18, 0xcd, 0x4b, 0x49, 0xc4, 0x80, 0x71, 0x7f, 0x92, 0x47, 0xf5, 0xf2, 0x81, 0x7c, 0x12, - 0x55, 0x0b, 0xd0, 0xad, 0x90, 0x2d, 0x1d, 0xe8, 0xa0, 0x1f, 0xe8, 0x60, 0x43, 0x07, 0xe6, 0xb1, - 0x51, 0x17, 0x04, 0x4b, 0x1e, 0xeb, 0x88, 0xbb, 0x59, 0x6a, 0xff, 0xad, 0x5a, 0xe5, 0xdf, 0xa1, - 0xab, 0x81, 0x37, 0x7d, 0x7e, 0x7d, 0xab, 0xcf, 0xe0, 0xe2, 0x7e, 0x65, 0x81, 0xe5, 0xca, 0x02, - 0x4f, 0x2b, 0x0b, 0xdc, 0xac, 0xad, 0xda, 0x72, 0x6d, 0xd5, 0x1e, 0xd7, 0x56, 0xed, 0xaa, 0x1b, - 0x52, 0x35, 0x9e, 0x7a, 0x8e, 0xcf, 0x23, 0x54, 0x1e, 0xf5, 0x94, 0x61, 0x4f, 0xea, 0x19, 0xcd, - 0x7a, 0xe8, 0x7a, 0x7b, 0x65, 0x35, 0x4f, 0x88, 0xf4, 0xea, 0xc5, 0x45, 0xcf, 0x5f, 0x02, 0x00, - 0x00, 0xff, 0xff, 0xd9, 0xf3, 0xfa, 0x2e, 0xbf, 0x02, 0x00, 0x00, + // 400 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0x3f, 0x8f, 0xda, 0x30, + 0x18, 0xc6, 0x71, 0x8b, 0x28, 0x89, 0xfa, 0x37, 0x45, 0x2a, 0x65, 0x48, 0x90, 0x27, 0x2a, 0xb5, + 0x71, 0xa1, 0x1b, 0x63, 0xd6, 0x6e, 0x91, 0xba, 0x74, 0x41, 0x4e, 0x62, 0x82, 0x85, 0x13, 0x47, + 0xb6, 0x41, 0xe5, 0x5b, 0x74, 0xbc, 0x91, 0xfd, 0xbe, 0xc8, 0x2d, 0x27, 0x31, 0xde, 0x14, 0x9d, + 0x60, 0xb9, 0x39, 0x9f, 0xe0, 0x94, 0xc4, 0x81, 0xfb, 0x27, 0x9d, 0x6e, 0x7b, 0xdf, 0x3c, 0xbf, + 0x27, 0x7e, 0x1e, 0xbd, 0xe6, 0x24, 0x22, 0x32, 0xe1, 0x12, 0x65, 0x82, 0xcf, 0x29, 0x23, 0x12, + 0xad, 0xc7, 0x01, 0x51, 0x78, 0x8c, 0x12, 0x1e, 0x11, 0x26, 0x67, 0x82, 0x30, 0xac, 0x28, 0x4f, + 0xe5, 0x82, 0x66, 0xd2, 0xcd, 0x04, 0x57, 0xdc, 0xfa, 0x52, 0x7b, 0xdc, 0xc6, 0xe3, 0x6a, 0xcf, + 0xa0, 0x17, 0xf3, 0x98, 0x57, 0x0c, 0x2a, 0xa7, 0x1a, 0x1f, 0x7c, 0x8d, 0x39, 0x8f, 0x19, 0x41, + 0xd5, 0x16, 0xac, 0xe6, 0x08, 0xa7, 0x1b, 0x2d, 0x39, 0x0f, 0x25, 0x45, 0x13, 0x22, 0x15, 0x4e, + 0xb2, 0xc6, 0x1b, 0xf2, 0xf2, 0xa9, 0x59, 0xfd, 0xd3, 0x7a, 0xd1, 0xd2, 0xcf, 0x67, 0x92, 0x87, + 0x0b, 0x4c, 0xd3, 0x19, 0xa3, 0xe9, 0x52, 0x3b, 0xe0, 0x39, 0x30, 0xdf, 0xfa, 0x77, 0xfa, 0x58, + 0xdf, 0xcd, 0x37, 0xa1, 0x20, 0x58, 0x71, 0xd1, 0x07, 0x43, 0x30, 0x32, 0x3c, 0xab, 0xc8, 0x9d, + 0xf7, 0x1b, 0x9c, 0xb0, 0x29, 0xd4, 0x02, 0xf4, 0x1b, 0xc4, 0x9a, 0x98, 0x86, 0x20, 0x21, 0xcd, + 0x28, 0x49, 0x55, 0xff, 0x55, 0xc5, 0xf7, 0x8a, 0xdc, 0xf9, 0x58, 0xf3, 0x47, 0x09, 0xfa, 0x27, + 0xcc, 0x42, 0x66, 0x57, 0xae, 0x02, 0x99, 0xe1, 0x90, 0xf4, 0x5f, 0x0f, 0xc1, 0xa8, 0xed, 0x7d, + 0x2e, 0x72, 0xe7, 0x43, 0x6d, 0x69, 0x14, 0xe8, 0x1f, 0xa1, 0x69, 0xf7, 0x6c, 0xeb, 0x80, 0x9b, + 0xad, 0x03, 0xe0, 0x25, 0x30, 0x8d, 0x3f, 0x92, 0x08, 0x8f, 0xf1, 0x70, 0x59, 0x46, 0x0d, 0xca, + 0x81, 0x3c, 0x11, 0x55, 0x0b, 0xd0, 0x6f, 0x90, 0x13, 0x1d, 0xe9, 0xa0, 0x8f, 0xe8, 0xe8, 0x48, + 0x47, 0xd6, 0x37, 0xb3, 0x23, 0x08, 0x96, 0x3c, 0xad, 0x22, 0x1a, 0xde, 0xa7, 0x22, 0x77, 0xde, + 0x35, 0xad, 0xca, 0xef, 0xd0, 0xd7, 0xc0, 0xbd, 0x3e, 0xed, 0x17, 0xf5, 0xf1, 0x7e, 0x5f, 0xec, + 0x6d, 0xb0, 0xdb, 0xdb, 0xe0, 0x7a, 0x6f, 0x83, 0xff, 0x07, 0xbb, 0xb5, 0x3b, 0xd8, 0xad, 0xab, + 0x83, 0xdd, 0xfa, 0x3b, 0x8e, 0xa9, 0x5a, 0xac, 0x02, 0x37, 0xe4, 0x09, 0xaa, 0x8f, 0xfa, 0x83, + 0xe1, 0x40, 0xea, 0x19, 0xad, 0x27, 0xe8, 0xdf, 0xe9, 0xca, 0x6a, 0x93, 0x11, 0x19, 0x74, 0xaa, + 0x8b, 0xfe, 0xba, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x28, 0x6f, 0x12, 0x0c, 0xbf, 0x02, 0x00, 0x00, } func (this *Relationship) Equal(that interface{}) bool { @@ -284,12 +284,10 @@ func (m *Relationship) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Subspace) > 0 { - i -= len(m.Subspace) - copy(dAtA[i:], m.Subspace) - i = encodeVarintModelsRelationships(dAtA, i, uint64(len(m.Subspace))) + if m.Subspace != 0 { + i = encodeVarintModelsRelationships(dAtA, i, uint64(m.Subspace)) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x18 } if len(m.Recipient) > 0 { i -= len(m.Recipient) @@ -328,12 +326,10 @@ func (m *UserBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Subspace) > 0 { - i -= len(m.Subspace) - copy(dAtA[i:], m.Subspace) - i = encodeVarintModelsRelationships(dAtA, i, uint64(len(m.Subspace))) + if m.Subspace != 0 { + i = encodeVarintModelsRelationships(dAtA, i, uint64(m.Subspace)) i-- - dAtA[i] = 0x22 + dAtA[i] = 0x20 } if len(m.Reason) > 0 { i -= len(m.Reason) @@ -384,9 +380,8 @@ func (m *Relationship) Size() (n int) { if l > 0 { n += 1 + l + sovModelsRelationships(uint64(l)) } - l = len(m.Subspace) - if l > 0 { - n += 1 + l + sovModelsRelationships(uint64(l)) + if m.Subspace != 0 { + n += 1 + sovModelsRelationships(uint64(m.Subspace)) } return n } @@ -409,9 +404,8 @@ func (m *UserBlock) Size() (n int) { if l > 0 { n += 1 + l + sovModelsRelationships(uint64(l)) } - l = len(m.Subspace) - if l > 0 { - n += 1 + l + sovModelsRelationships(uint64(l)) + if m.Subspace != 0 { + n += 1 + sovModelsRelationships(uint64(m.Subspace)) } return n } @@ -516,10 +510,10 @@ func (m *Relationship) Unmarshal(dAtA []byte) error { m.Recipient = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 2 { + if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) } - var stringLen uint64 + m.Subspace = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowModelsRelationships @@ -529,24 +523,11 @@ func (m *Relationship) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.Subspace |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthModelsRelationships - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthModelsRelationships - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Subspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipModelsRelationships(dAtA[iNdEx:]) @@ -694,10 +675,10 @@ func (m *UserBlock) Unmarshal(dAtA []byte) error { m.Reason = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: - if wireType != 2 { + if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) } - var stringLen uint64 + m.Subspace = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowModelsRelationships @@ -707,24 +688,11 @@ func (m *UserBlock) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.Subspace |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthModelsRelationships - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthModelsRelationships - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Subspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipModelsRelationships(dAtA[iNdEx:]) diff --git a/x/profiles/types/models_relationships_test.go b/x/profiles/types/models_relationships_test.go index 47e5b71190..fc67e9a066 100644 --- a/x/profiles/types/models_relationships_test.go +++ b/x/profiles/types/models_relationships_test.go @@ -21,7 +21,7 @@ func TestRelationship_Validate(t *testing.T) { relationship: types.NewRelationship( "", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "", + 0, ), shouldErr: true, }, @@ -30,16 +30,7 @@ func TestRelationship_Validate(t *testing.T) { relationship: types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "", - "", - ), - shouldErr: true, - }, - { - name: "invalid subspace returns error", - relationship: types.NewRelationship( - "cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4", - "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "subspace", + 0, ), shouldErr: true, }, @@ -48,7 +39,7 @@ func TestRelationship_Validate(t *testing.T) { relationship: types.NewRelationship( "cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4", "cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4", - "", + 0, ), shouldErr: true, }, @@ -57,7 +48,7 @@ func TestRelationship_Validate(t *testing.T) { relationship: types.NewRelationship( "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4", - "", + 0, ), shouldErr: false, }, @@ -79,7 +70,7 @@ func TestRelationship_Validate(t *testing.T) { func TestRelationshipMarshaling(t *testing.T) { cdc, _ := app.MakeCodecs() - relationship := types.NewRelationship("creator", "recipient_1", "subspace") + relationship := types.NewRelationship("creator", "recipient_1", 1) marshalled := types.MustMarshalRelationship(cdc, relationship) unmarshalled := types.MustUnmarshalRelationship(cdc, marshalled) require.Equal(t, relationship, unmarshalled) @@ -99,7 +90,7 @@ func TestUserBlock_Validate(t *testing.T) { "", "cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4", "reason", - "", + 0, ), shouldErr: true, }, @@ -109,7 +100,7 @@ func TestUserBlock_Validate(t *testing.T) { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "", "reason", - "", + 0, ), shouldErr: true, }, @@ -119,17 +110,7 @@ func TestUserBlock_Validate(t *testing.T) { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "reason", - "", - ), - shouldErr: true, - }, - { - name: "invalid subspace returns error", - userBlock: types.NewUserBlock( - "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4", - "reason", - "yeah", + 0, ), shouldErr: true, }, @@ -139,7 +120,7 @@ func TestUserBlock_Validate(t *testing.T) { "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4", "reason", - "", + 0, ), shouldErr: false, }, diff --git a/x/profiles/types/msgs_relationships.go b/x/profiles/types/msgs_relationships.go index be0fbcf7b8..3ace35e34c 100644 --- a/x/profiles/types/msgs_relationships.go +++ b/x/profiles/types/msgs_relationships.go @@ -9,7 +9,7 @@ import ( // --- MsgSaveProfile // ---------------------- -func NewMsgCreateRelationship(creator, recipient, subspace string) *MsgCreateRelationship { +func NewMsgCreateRelationship(creator, recipient string, subspace uint64) *MsgCreateRelationship { return &MsgCreateRelationship{ Sender: creator, Receiver: recipient, @@ -41,10 +41,6 @@ func (msg MsgCreateRelationship) ValidateBasic() error { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "sender and receiver must be different") } - if !IsValidSubspace(msg.Subspace) { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid subspace") - } - return nil } @@ -61,7 +57,7 @@ func (msg MsgCreateRelationship) GetSigners() []sdk.AccAddress { // ___________________________________________________________________________________________________________________ -func NewMsgDeleteRelationship(user, counterparty, subspace string) *MsgDeleteRelationship { +func NewMsgDeleteRelationship(user, counterparty string, subspace uint64) *MsgDeleteRelationship { return &MsgDeleteRelationship{ User: user, Counterparty: counterparty, @@ -93,10 +89,6 @@ func (msg MsgDeleteRelationship) ValidateBasic() error { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "user and counterparty must be different") } - if !IsValidSubspace(msg.Subspace) { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid subspace") - } - return nil } @@ -113,7 +105,7 @@ func (msg MsgDeleteRelationship) GetSigners() []sdk.AccAddress { // ___________________________________________________________________________________________________________________ -func NewMsgBlockUser(blocker, blocked, reason, subspace string) *MsgBlockUser { +func NewMsgBlockUser(blocker, blocked, reason string, subspace uint64) *MsgBlockUser { return &MsgBlockUser{ Blocker: blocker, Blocked: blocked, @@ -146,10 +138,6 @@ func (msg MsgBlockUser) ValidateBasic() error { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "blocker and blocked must be different") } - if !IsValidSubspace(msg.Subspace) { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid subspace") - } - return nil } @@ -166,7 +154,7 @@ func (msg MsgBlockUser) GetSigners() []sdk.AccAddress { // ___________________________________________________________________________________________________________________ -func NewMsgUnblockUser(blocker, blocked, subspace string) *MsgUnblockUser { +func NewMsgUnblockUser(blocker, blocked string, subspace uint64) *MsgUnblockUser { return &MsgUnblockUser{ Blocker: blocker, Blocked: blocked, @@ -198,10 +186,6 @@ func (msg MsgUnblockUser) ValidateBasic() error { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "blocker and blocked must be different") } - if !IsValidSubspace(msg.Subspace) { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid subspace") - } - return nil } diff --git a/x/profiles/types/msgs_relationships.pb.go b/x/profiles/types/msgs_relationships.pb.go index a670fc29ff..cc0dbfa4db 100644 --- a/x/profiles/types/msgs_relationships.pb.go +++ b/x/profiles/types/msgs_relationships.pb.go @@ -30,7 +30,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type MsgCreateRelationship struct { Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` Receiver string `protobuf:"bytes,2,opt,name=receiver,proto3" json:"receiver,omitempty" yaml:"receiver"` - Subspace string `protobuf:"bytes,3,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` + Subspace uint64 `protobuf:"varint,3,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` } func (m *MsgCreateRelationship) Reset() { *m = MsgCreateRelationship{} } @@ -109,7 +109,7 @@ var xxx_messageInfo_MsgCreateRelationshipResponse proto.InternalMessageInfo type MsgDeleteRelationship struct { User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty" yaml:"user"` Counterparty string `protobuf:"bytes,2,opt,name=counterparty,proto3" json:"counterparty,omitempty" yaml:"counterparty"` - Subspace string `protobuf:"bytes,3,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` + Subspace uint64 `protobuf:"varint,3,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` } func (m *MsgDeleteRelationship) Reset() { *m = MsgDeleteRelationship{} } @@ -159,11 +159,11 @@ func (m *MsgDeleteRelationship) GetCounterparty() string { return "" } -func (m *MsgDeleteRelationship) GetSubspace() string { +func (m *MsgDeleteRelationship) GetSubspace() uint64 { if m != nil { return m.Subspace } - return "" + return 0 } // MsgDeleteRelationshipResponse defines the Msg/DeleteRelationship response @@ -210,7 +210,7 @@ type MsgBlockUser struct { Blocker string `protobuf:"bytes,1,opt,name=blocker,proto3" json:"blocker,omitempty" yaml:"blocker"` Blocked string `protobuf:"bytes,2,opt,name=blocked,proto3" json:"blocked,omitempty" yaml:"blocked"` Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty" yaml:"reason"` - Subspace string `protobuf:"bytes,4,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` + Subspace uint64 `protobuf:"varint,4,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` } func (m *MsgBlockUser) Reset() { *m = MsgBlockUser{} } @@ -267,11 +267,11 @@ func (m *MsgBlockUser) GetReason() string { return "" } -func (m *MsgBlockUser) GetSubspace() string { +func (m *MsgBlockUser) GetSubspace() uint64 { if m != nil { return m.Subspace } - return "" + return 0 } // MsgBlockUserResponse defines the Msg/BlockUser response type. @@ -315,7 +315,7 @@ var xxx_messageInfo_MsgBlockUserResponse proto.InternalMessageInfo type MsgUnblockUser struct { Blocker string `protobuf:"bytes,1,opt,name=blocker,proto3" json:"blocker,omitempty" yaml:"blocker"` Blocked string `protobuf:"bytes,2,opt,name=blocked,proto3" json:"blocked,omitempty" yaml:"blocked"` - Subspace string `protobuf:"bytes,4,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` + Subspace uint64 `protobuf:"varint,4,opt,name=subspace,proto3" json:"subspace,omitempty" yaml:"subspace"` } func (m *MsgUnblockUser) Reset() { *m = MsgUnblockUser{} } @@ -365,11 +365,11 @@ func (m *MsgUnblockUser) GetBlocked() string { return "" } -func (m *MsgUnblockUser) GetSubspace() string { +func (m *MsgUnblockUser) GetSubspace() uint64 { if m != nil { return m.Subspace } - return "" + return 0 } // MsgUnblockUserResponse defines the Msg/UnblockUser response type. @@ -425,39 +425,39 @@ func init() { } var fileDescriptor_2d797ddfd6bfe874 = []byte{ - // 507 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x93, 0x31, 0x6f, 0xd3, 0x4c, - 0x18, 0xc7, 0xe3, 0xf7, 0xad, 0x4a, 0x39, 0x4a, 0x2b, 0xd2, 0xd2, 0x86, 0x4a, 0xd8, 0xe8, 0x58, - 0x40, 0x2a, 0x39, 0x52, 0xb6, 0xb2, 0x05, 0x36, 0x94, 0xc5, 0x52, 0x17, 0x96, 0xe8, 0x6c, 0x3f, - 0xbd, 0x46, 0x38, 0x3e, 0x73, 0xcf, 0x39, 0x22, 0xdf, 0x80, 0x91, 0x2f, 0x80, 0xd4, 0x99, 0x81, - 0x8f, 0x81, 0x18, 0x3b, 0x32, 0x59, 0x28, 0x59, 0x98, 0xfd, 0x09, 0x90, 0x7d, 0x67, 0x37, 0x69, - 0x8b, 0x4a, 0x17, 0x36, 0xdf, 0xf3, 0xfc, 0xfe, 0xf6, 0xff, 0x27, 0xeb, 0xc8, 0xf3, 0x08, 0x70, - 0x2c, 0x91, 0xa5, 0x4a, 0x1e, 0x8f, 0x62, 0x40, 0x36, 0xe9, 0x05, 0xa0, 0x79, 0x8f, 0x8d, 0x51, - 0xe0, 0x50, 0x41, 0xcc, 0xf5, 0x48, 0x26, 0x78, 0x32, 0x4a, 0xb1, 0x9b, 0x2a, 0xa9, 0x65, 0x7b, - 0xd7, 0x24, 0xba, 0x75, 0xa2, 0x6b, 0x13, 0x7b, 0xdb, 0x42, 0x0a, 0x59, 0x31, 0xac, 0x7c, 0x32, - 0xf8, 0xde, 0x03, 0x21, 0xa5, 0x88, 0x81, 0x55, 0xa7, 0x20, 0x3b, 0x66, 0x3c, 0x99, 0xd6, 0xab, - 0x50, 0x96, 0x6f, 0x1a, 0x9a, 0x8c, 0x39, 0xd8, 0xd5, 0xfe, 0x1f, 0x6b, 0xc9, 0x08, 0xe2, 0x2a, - 0x52, 0xce, 0x2d, 0x7d, 0x70, 0x0d, 0x7d, 0x85, 0xc6, 0xb5, 0x99, 0x48, 0x73, 0x31, 0x54, 0xf0, - 0x3e, 0x03, 0xd4, 0x36, 0x43, 0xbf, 0x3a, 0xe4, 0xfe, 0x00, 0xc5, 0x2b, 0x05, 0x5c, 0x83, 0xbf, - 0xf0, 0xd2, 0xf6, 0x53, 0xb2, 0x8a, 0x90, 0x44, 0xa0, 0x3a, 0xce, 0x23, 0xe7, 0xc9, 0xed, 0xfe, - 0xbd, 0x22, 0xf7, 0xee, 0x4e, 0xf9, 0x38, 0x3e, 0xa4, 0x66, 0x4e, 0x7d, 0x0b, 0xb4, 0x19, 0x59, - 0x53, 0x10, 0xc2, 0x68, 0x02, 0xaa, 0xf3, 0x5f, 0x05, 0x6f, 0x15, 0xb9, 0xb7, 0x69, 0xe0, 0x7a, - 0x43, 0xfd, 0x06, 0x2a, 0x03, 0x98, 0x05, 0x98, 0xf2, 0x10, 0x3a, 0xff, 0x5f, 0x0c, 0xd4, 0x1b, - 0xea, 0x37, 0xd0, 0xe1, 0xda, 0xc7, 0x53, 0xaf, 0xf5, 0xeb, 0xd4, 0x6b, 0x51, 0x8f, 0x3c, 0xbc, - 0xb2, 0xaf, 0x0f, 0x98, 0xca, 0x04, 0x81, 0x7e, 0x31, 0x46, 0xaf, 0x21, 0x86, 0x0b, 0x46, 0x8f, - 0xc9, 0x4a, 0x86, 0x8d, 0xcf, 0x66, 0x91, 0x7b, 0x77, 0xcc, 0x17, 0xcb, 0x29, 0xf5, 0xab, 0x65, - 0xfb, 0x25, 0x59, 0x0f, 0x65, 0x96, 0x68, 0x50, 0x29, 0x57, 0x7a, 0x6a, 0x7d, 0x76, 0x8b, 0xdc, - 0xdb, 0x32, 0xf0, 0xe2, 0x96, 0xfa, 0x4b, 0xf0, 0x8d, 0xbd, 0xac, 0xcd, 0xe5, 0xae, 0x8d, 0xcd, - 0x37, 0x87, 0xac, 0x0f, 0x50, 0xf4, 0x63, 0x19, 0xbe, 0x3b, 0x2a, 0xfb, 0xed, 0x93, 0x5b, 0x41, - 0x79, 0x68, 0x3c, 0xda, 0x45, 0xee, 0x6d, 0x98, 0x2f, 0xd8, 0x05, 0xf5, 0x6b, 0xe4, 0x9c, 0x8e, - 0xac, 0xc8, 0x25, 0x3a, 0x6a, 0xe8, 0xa8, 0xfc, 0xe5, 0x0a, 0x38, 0xca, 0xc4, 0x96, 0x5f, 0xf8, - 0xe5, 0x66, 0x4e, 0x7d, 0x0b, 0x2c, 0x99, 0xae, 0xfc, 0x8d, 0xe9, 0x0e, 0xd9, 0x5e, 0xf4, 0x68, - 0x04, 0x3f, 0x3b, 0x64, 0x63, 0x80, 0xe2, 0x28, 0x09, 0xfe, 0x89, 0xe2, 0x8d, 0x7b, 0x77, 0xc8, - 0xce, 0x72, 0xbd, 0xba, 0x79, 0xff, 0xcd, 0xf7, 0x99, 0xeb, 0x9c, 0xcd, 0x5c, 0xe7, 0xe7, 0xcc, - 0x75, 0x3e, 0xcd, 0xdd, 0xd6, 0xd9, 0xdc, 0x6d, 0xfd, 0x98, 0xbb, 0xad, 0xb7, 0x3d, 0x31, 0xd2, - 0x27, 0x59, 0xd0, 0x0d, 0xe5, 0x98, 0x99, 0x3b, 0xf9, 0x2c, 0xe6, 0x01, 0xda, 0x67, 0x36, 0x39, - 0x60, 0x1f, 0xce, 0x2f, 0xa9, 0x9e, 0xa6, 0x80, 0xc1, 0x6a, 0x75, 0x1d, 0x5f, 0xfc, 0x0e, 0x00, - 0x00, 0xff, 0xff, 0xd0, 0x1c, 0x97, 0x0c, 0xbd, 0x04, 0x00, 0x00, + // 509 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x93, 0xb1, 0x6e, 0xd3, 0x40, + 0x18, 0xc7, 0x63, 0x88, 0x4a, 0x39, 0x4a, 0x2b, 0xd2, 0xd2, 0x86, 0x4a, 0xd8, 0xd5, 0xb1, 0x14, + 0xa9, 0xe4, 0x48, 0xd9, 0xca, 0x16, 0xd8, 0x50, 0x16, 0x4b, 0x5d, 0x58, 0xa2, 0xb3, 0xfd, 0xf5, + 0x1a, 0xe1, 0xf8, 0xcc, 0x7d, 0xe7, 0x88, 0xbc, 0x01, 0x23, 0x2f, 0x80, 0xd4, 0x99, 0x81, 0xc7, + 0x40, 0x8c, 0x1d, 0x99, 0x22, 0x94, 0x2c, 0xcc, 0x7e, 0x02, 0x64, 0xdf, 0xd9, 0x4d, 0x68, 0x51, + 0xe9, 0xc2, 0xe6, 0xfb, 0xbe, 0xdf, 0xdf, 0xfe, 0xff, 0x64, 0x1d, 0x79, 0x1e, 0x01, 0x8e, 0x24, + 0xb2, 0x54, 0xc9, 0x93, 0x61, 0x0c, 0xc8, 0xc6, 0xdd, 0x00, 0x34, 0xef, 0xb2, 0x11, 0x0a, 0x1c, + 0x28, 0x88, 0xb9, 0x1e, 0xca, 0x04, 0x4f, 0x87, 0x29, 0x76, 0x52, 0x25, 0xb5, 0x6c, 0xed, 0x98, + 0x44, 0xa7, 0x4a, 0x74, 0x6c, 0x62, 0x77, 0x4b, 0x48, 0x21, 0x4b, 0x86, 0x15, 0x4f, 0x06, 0xdf, + 0x7d, 0x24, 0xa4, 0x14, 0x31, 0xb0, 0xf2, 0x14, 0x64, 0x27, 0x8c, 0x27, 0x93, 0x6a, 0x15, 0xca, + 0xe2, 0x4d, 0x03, 0x93, 0x31, 0x07, 0xbb, 0x3a, 0xf8, 0x6b, 0x2d, 0x19, 0x41, 0x5c, 0x46, 0x8a, + 0xb9, 0xa5, 0x0f, 0xaf, 0xa1, 0xaf, 0xd0, 0xb8, 0x36, 0x13, 0x69, 0x2e, 0x06, 0x0a, 0xde, 0x67, + 0x80, 0xda, 0x66, 0xe8, 0x57, 0x87, 0x3c, 0xec, 0xa3, 0x78, 0xa5, 0x80, 0x6b, 0xf0, 0x17, 0x5e, + 0xda, 0x7a, 0x4a, 0x56, 0x10, 0x92, 0x08, 0x54, 0xdb, 0xd9, 0x73, 0xf6, 0xef, 0xf6, 0x1e, 0xe4, + 0x53, 0xef, 0xfe, 0x84, 0x8f, 0xe2, 0x23, 0x6a, 0xe6, 0xd4, 0xb7, 0x40, 0x8b, 0x91, 0x55, 0x05, + 0x21, 0x0c, 0xc7, 0xa0, 0xda, 0xb7, 0x4a, 0x78, 0x33, 0x9f, 0x7a, 0x1b, 0x06, 0xae, 0x36, 0xd4, + 0xaf, 0xa1, 0x22, 0x80, 0x59, 0x80, 0x29, 0x0f, 0xa1, 0x7d, 0x7b, 0xcf, 0xd9, 0x6f, 0x2e, 0x06, + 0xaa, 0x0d, 0xf5, 0x6b, 0xe8, 0x68, 0xf5, 0xe3, 0x99, 0xd7, 0xf8, 0x75, 0xe6, 0x35, 0xa8, 0x47, + 0x1e, 0x5f, 0xd9, 0xd7, 0x07, 0x4c, 0x65, 0x82, 0x40, 0xbf, 0x18, 0xa3, 0xd7, 0x10, 0xc3, 0x1f, + 0x46, 0x4f, 0x48, 0x33, 0xc3, 0xda, 0x67, 0x23, 0x9f, 0x7a, 0xf7, 0xcc, 0x17, 0x8b, 0x29, 0xf5, + 0xcb, 0x65, 0xeb, 0x25, 0x59, 0x0b, 0x65, 0x96, 0x68, 0x50, 0x29, 0x57, 0x7a, 0x62, 0x7d, 0x76, + 0xf2, 0xa9, 0xb7, 0x69, 0xe0, 0xc5, 0x2d, 0xf5, 0x97, 0xe0, 0x1b, 0x7b, 0x59, 0x9b, 0xcb, 0x5d, + 0x6b, 0x9b, 0x6f, 0x0e, 0x59, 0xeb, 0xa3, 0xe8, 0xc5, 0x32, 0x7c, 0x77, 0x5c, 0xf4, 0x3b, 0x20, + 0x77, 0x82, 0xe2, 0x50, 0x7b, 0xb4, 0xf2, 0xa9, 0xb7, 0x6e, 0xbe, 0x60, 0x17, 0xd4, 0xaf, 0x90, + 0x0b, 0x3a, 0xb2, 0x22, 0x97, 0xe8, 0xa8, 0xa6, 0xa3, 0xe2, 0x97, 0x2b, 0xe0, 0x28, 0x93, 0xb2, + 0xfc, 0xd2, 0x2f, 0x37, 0x73, 0xea, 0x5b, 0x60, 0xc9, 0xb4, 0xf9, 0x2f, 0xa6, 0xdb, 0x64, 0x6b, + 0xd1, 0xa3, 0x16, 0xfc, 0xec, 0x90, 0xf5, 0x3e, 0x8a, 0xe3, 0x24, 0xf8, 0x2f, 0x8a, 0x37, 0xee, + 0xdd, 0x26, 0xdb, 0xcb, 0xf5, 0xaa, 0xe6, 0xbd, 0x37, 0xdf, 0x67, 0xae, 0x73, 0x3e, 0x73, 0x9d, + 0x9f, 0x33, 0xd7, 0xf9, 0x34, 0x77, 0x1b, 0xe7, 0x73, 0xb7, 0xf1, 0x63, 0xee, 0x36, 0xde, 0x76, + 0xc5, 0x50, 0x9f, 0x66, 0x41, 0x27, 0x94, 0x23, 0x66, 0xee, 0xe4, 0xb3, 0x98, 0x07, 0x68, 0x9f, + 0xd9, 0xf8, 0x90, 0x7d, 0xb8, 0xb8, 0xa4, 0x7a, 0x92, 0x02, 0x06, 0x2b, 0xe5, 0x75, 0x7c, 0xf1, + 0x3b, 0x00, 0x00, 0xff, 0xff, 0x01, 0x5e, 0xbb, 0xac, 0xbd, 0x04, 0x00, 0x00, } func (m *MsgCreateRelationship) Marshal() (dAtA []byte, err error) { @@ -480,12 +480,10 @@ func (m *MsgCreateRelationship) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Subspace) > 0 { - i -= len(m.Subspace) - copy(dAtA[i:], m.Subspace) - i = encodeVarintMsgsRelationships(dAtA, i, uint64(len(m.Subspace))) + if m.Subspace != 0 { + i = encodeVarintMsgsRelationships(dAtA, i, uint64(m.Subspace)) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x18 } if len(m.Receiver) > 0 { i -= len(m.Receiver) @@ -547,12 +545,10 @@ func (m *MsgDeleteRelationship) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Subspace) > 0 { - i -= len(m.Subspace) - copy(dAtA[i:], m.Subspace) - i = encodeVarintMsgsRelationships(dAtA, i, uint64(len(m.Subspace))) + if m.Subspace != 0 { + i = encodeVarintMsgsRelationships(dAtA, i, uint64(m.Subspace)) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x18 } if len(m.Counterparty) > 0 { i -= len(m.Counterparty) @@ -614,12 +610,10 @@ func (m *MsgBlockUser) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Subspace) > 0 { - i -= len(m.Subspace) - copy(dAtA[i:], m.Subspace) - i = encodeVarintMsgsRelationships(dAtA, i, uint64(len(m.Subspace))) + if m.Subspace != 0 { + i = encodeVarintMsgsRelationships(dAtA, i, uint64(m.Subspace)) i-- - dAtA[i] = 0x22 + dAtA[i] = 0x20 } if len(m.Reason) > 0 { i -= len(m.Reason) @@ -688,12 +682,10 @@ func (m *MsgUnblockUser) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Subspace) > 0 { - i -= len(m.Subspace) - copy(dAtA[i:], m.Subspace) - i = encodeVarintMsgsRelationships(dAtA, i, uint64(len(m.Subspace))) + if m.Subspace != 0 { + i = encodeVarintMsgsRelationships(dAtA, i, uint64(m.Subspace)) i-- - dAtA[i] = 0x22 + dAtA[i] = 0x20 } if len(m.Blocked) > 0 { i -= len(m.Blocked) @@ -760,9 +752,8 @@ func (m *MsgCreateRelationship) Size() (n int) { if l > 0 { n += 1 + l + sovMsgsRelationships(uint64(l)) } - l = len(m.Subspace) - if l > 0 { - n += 1 + l + sovMsgsRelationships(uint64(l)) + if m.Subspace != 0 { + n += 1 + sovMsgsRelationships(uint64(m.Subspace)) } return n } @@ -790,9 +781,8 @@ func (m *MsgDeleteRelationship) Size() (n int) { if l > 0 { n += 1 + l + sovMsgsRelationships(uint64(l)) } - l = len(m.Subspace) - if l > 0 { - n += 1 + l + sovMsgsRelationships(uint64(l)) + if m.Subspace != 0 { + n += 1 + sovMsgsRelationships(uint64(m.Subspace)) } return n } @@ -824,9 +814,8 @@ func (m *MsgBlockUser) Size() (n int) { if l > 0 { n += 1 + l + sovMsgsRelationships(uint64(l)) } - l = len(m.Subspace) - if l > 0 { - n += 1 + l + sovMsgsRelationships(uint64(l)) + if m.Subspace != 0 { + n += 1 + sovMsgsRelationships(uint64(m.Subspace)) } return n } @@ -854,9 +843,8 @@ func (m *MsgUnblockUser) Size() (n int) { if l > 0 { n += 1 + l + sovMsgsRelationships(uint64(l)) } - l = len(m.Subspace) - if l > 0 { - n += 1 + l + sovMsgsRelationships(uint64(l)) + if m.Subspace != 0 { + n += 1 + sovMsgsRelationships(uint64(m.Subspace)) } return n } @@ -970,10 +958,10 @@ func (m *MsgCreateRelationship) Unmarshal(dAtA []byte) error { m.Receiver = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 2 { + if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) } - var stringLen uint64 + m.Subspace = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowMsgsRelationships @@ -983,24 +971,11 @@ func (m *MsgCreateRelationship) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.Subspace |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthMsgsRelationships - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthMsgsRelationships - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Subspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipMsgsRelationships(dAtA[iNdEx:]) @@ -1166,10 +1141,10 @@ func (m *MsgDeleteRelationship) Unmarshal(dAtA []byte) error { m.Counterparty = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 2 { + if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) } - var stringLen uint64 + m.Subspace = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowMsgsRelationships @@ -1179,24 +1154,11 @@ func (m *MsgDeleteRelationship) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.Subspace |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthMsgsRelationships - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthMsgsRelationships - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Subspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipMsgsRelationships(dAtA[iNdEx:]) @@ -1394,10 +1356,10 @@ func (m *MsgBlockUser) Unmarshal(dAtA []byte) error { m.Reason = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: - if wireType != 2 { + if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) } - var stringLen uint64 + m.Subspace = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowMsgsRelationships @@ -1407,24 +1369,11 @@ func (m *MsgBlockUser) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.Subspace |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthMsgsRelationships - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthMsgsRelationships - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Subspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipMsgsRelationships(dAtA[iNdEx:]) @@ -1590,10 +1539,10 @@ func (m *MsgUnblockUser) Unmarshal(dAtA []byte) error { m.Blocked = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: - if wireType != 2 { + if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) } - var stringLen uint64 + m.Subspace = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowMsgsRelationships @@ -1603,24 +1552,11 @@ func (m *MsgUnblockUser) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.Subspace |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthMsgsRelationships - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthMsgsRelationships - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Subspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipMsgsRelationships(dAtA[iNdEx:]) diff --git a/x/profiles/types/msgs_relationships_test.go b/x/profiles/types/msgs_relationships_test.go index eb1781bcec..8f85f54d21 100644 --- a/x/profiles/types/msgs_relationships_test.go +++ b/x/profiles/types/msgs_relationships_test.go @@ -13,7 +13,7 @@ import ( var msgCreateRelationship = types.NewMsgCreateRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "", + 0, ) func TestMsgCreateRelationship_Route(t *testing.T) { @@ -35,7 +35,7 @@ func TestMsgCreateRelationship_ValidateBasic(t *testing.T) { msg: types.NewMsgCreateRelationship( "", "", - "", + 0, ), shouldErr: true, }, @@ -44,7 +44,7 @@ func TestMsgCreateRelationship_ValidateBasic(t *testing.T) { msg: types.NewMsgCreateRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "", - "", + 0, ), shouldErr: true, }, @@ -53,16 +53,7 @@ func TestMsgCreateRelationship_ValidateBasic(t *testing.T) { msg: types.NewMsgCreateRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "", - ), - shouldErr: true, - }, - { - name: "invalid subspace returns error", - msg: types.NewMsgCreateRelationship( - "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "1234", + 0, ), shouldErr: true, }, @@ -102,7 +93,7 @@ func TestMsgCreateRelationship_GetSigners(t *testing.T) { var msgDeleteRelationships = types.NewMsgDeleteRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "", + 0, ) func TestMsgDeleteRelationships_Route(t *testing.T) { @@ -124,7 +115,7 @@ func TestMsgDeleteRelationships_ValidateBasic(t *testing.T) { msg: types.NewMsgDeleteRelationship( "", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "", + 0, ), shouldErr: true, }, @@ -133,7 +124,7 @@ func TestMsgDeleteRelationships_ValidateBasic(t *testing.T) { msg: types.NewMsgDeleteRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "", - "", + 0, ), shouldErr: true, }, @@ -142,16 +133,7 @@ func TestMsgDeleteRelationships_ValidateBasic(t *testing.T) { msg: types.NewMsgDeleteRelationship( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "", - ), - shouldErr: true, - }, - { - name: "invalid subspace returns error", - msg: types.NewMsgDeleteRelationship( - "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "1234", + 0, ), shouldErr: true, }, @@ -192,7 +174,7 @@ var msgBlockUser = types.NewMsgBlockUser( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "reason", - "", + 0, ) func TestMsgBlockUser_Route(t *testing.T) { @@ -215,7 +197,7 @@ func TestMsgBlockUser_ValidateBasic(t *testing.T) { "", "", "", - "", + 0, ), shouldErr: true, }, @@ -225,7 +207,7 @@ func TestMsgBlockUser_ValidateBasic(t *testing.T) { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "", "", - "", + 0, ), shouldErr: true, }, @@ -235,17 +217,7 @@ func TestMsgBlockUser_ValidateBasic(t *testing.T) { "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "", - "", - ), - shouldErr: true, - }, - { - name: "invalid subspace returns error", - msg: types.NewMsgBlockUser( - "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "", - "yeah", + 0, ), shouldErr: true, }, @@ -285,7 +257,7 @@ func TestMsgBlockUser_GetSigners(t *testing.T) { var msgUnblockUser = types.NewMsgUnblockUser( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "", + 0, ) func TestMsgUnblockUser_Route(t *testing.T) { @@ -307,7 +279,7 @@ func TestMsgUnblockUser_ValidateBasic(t *testing.T) { msg: types.NewMsgUnblockUser( "", "", - "", + 0, ), shouldErr: true, }, @@ -316,7 +288,7 @@ func TestMsgUnblockUser_ValidateBasic(t *testing.T) { msg: types.NewMsgUnblockUser( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "", - "", + 0, ), shouldErr: true, }, @@ -325,16 +297,7 @@ func TestMsgUnblockUser_ValidateBasic(t *testing.T) { msg: types.NewMsgUnblockUser( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "", - ), - shouldErr: true, - }, - { - name: "invalid subspace returns error", - msg: types.NewMsgUnblockUser( - "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", - "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "yeah", + 0, ), shouldErr: true, }, @@ -343,7 +306,7 @@ func TestMsgUnblockUser_ValidateBasic(t *testing.T) { msg: types.NewMsgUnblockUser( "cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", - "", + 0, ), shouldErr: false, }, diff --git a/x/profiles/types/query_relationships.pb.go b/x/profiles/types/query_relationships.pb.go index ce3d6fea3a..f8b8b6aac2 100644 --- a/x/profiles/types/query_relationships.pb.go +++ b/x/profiles/types/query_relationships.pb.go @@ -33,7 +33,7 @@ type QueryRelationshipsRequest struct { // address of the user to query the relationships for User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` // subspace to query the relationships for - SubspaceId string `protobuf:"bytes,2,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty"` + SubspaceId uint64 `protobuf:"varint,2,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty"` // pagination defines an optional pagination for the request. Pagination *query.PageRequest `protobuf:"bytes,3,opt,name=pagination,proto3" json:"pagination,omitempty"` } @@ -131,7 +131,7 @@ func (m *QueryRelationshipsResponse) GetPagination() *query.PageResponse { type QueryBlocksRequest struct { // address of the user to query the blocks for User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` - SubspaceId string `protobuf:"bytes,2,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty"` + SubspaceId uint64 `protobuf:"varint,2,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty"` Pagination *query.PageRequest `protobuf:"bytes,3,opt,name=pagination,proto3" json:"pagination,omitempty"` } @@ -234,36 +234,36 @@ func init() { } var fileDescriptor_c0b8922e87a25523 = []byte{ - // 450 bytes of a gzipped FileDescriptorProto + // 452 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x93, 0xb1, 0x8e, 0xd3, 0x40, - 0x10, 0x86, 0xbd, 0x77, 0xa7, 0x13, 0x6c, 0x44, 0xb3, 0x20, 0x91, 0x44, 0xc8, 0x89, 0x22, 0x01, - 0x11, 0x12, 0xbb, 0x4a, 0xe8, 0xa8, 0x50, 0x0a, 0x10, 0xa2, 0xe1, 0x2c, 0xd1, 0xd0, 0x44, 0xbb, - 0xf1, 0x9c, 0xcf, 0xc2, 0xf1, 0xee, 0x79, 0xec, 0x13, 0x79, 0x03, 0x4a, 0x7a, 0x9a, 0x88, 0xa7, - 0xe0, 0x11, 0xae, 0xbc, 0x92, 0x0a, 0xa1, 0xa4, 0xe1, 0x31, 0x90, 0x77, 0x37, 0x9c, 0x2d, 0x5d, - 0x44, 0x43, 0x41, 0x37, 0xb3, 0x33, 0xff, 0xcc, 0x37, 0x7f, 0x62, 0x3a, 0x89, 0x01, 0x97, 0x1a, - 0x85, 0x29, 0xf4, 0x69, 0x9a, 0x01, 0x8a, 0x8b, 0x89, 0x82, 0x52, 0x4e, 0xc4, 0x79, 0x05, 0xc5, - 0x6a, 0x5e, 0x40, 0x26, 0xcb, 0x54, 0xe7, 0x78, 0x96, 0x1a, 0xe4, 0xa6, 0xd0, 0xa5, 0x66, 0xf7, - 0x9d, 0x84, 0xef, 0x24, 0xdc, 0x4b, 0xfa, 0xf7, 0x12, 0x9d, 0x68, 0xdb, 0x23, 0xea, 0xc8, 0xb5, - 0xf7, 0x1f, 0x24, 0x5a, 0x27, 0x19, 0x08, 0x69, 0x52, 0x21, 0xf3, 0x5c, 0x97, 0x6e, 0xa0, 0xaf, - 0xf6, 0x7c, 0xd5, 0x66, 0xaa, 0x3a, 0x15, 0x32, 0x5f, 0xf9, 0xd2, 0x74, 0x1f, 0xda, 0x52, 0xc7, - 0x90, 0xe1, 0x4d, 0x6c, 0xfd, 0xde, 0x42, 0xd7, 0x9a, 0xb9, 0xa3, 0x70, 0x89, 0x2f, 0x3d, 0x71, - 0x99, 0x50, 0x12, 0xc1, 0x5d, 0xf7, 0x67, 0xa0, 0x91, 0x49, 0x9a, 0xdb, 0x59, 0xae, 0x77, 0xf4, - 0x95, 0xd0, 0xde, 0x49, 0xdd, 0x12, 0x35, 0x77, 0x44, 0x70, 0x5e, 0x01, 0x96, 0x8c, 0xd1, 0xa3, - 0x0a, 0xa1, 0xe8, 0x92, 0x21, 0x19, 0xdf, 0x8e, 0x6c, 0xcc, 0x06, 0xb4, 0x83, 0x95, 0x42, 0x23, - 0x17, 0x30, 0x4f, 0xe3, 0xee, 0x81, 0x2d, 0xd1, 0xdd, 0xd3, 0xeb, 0x98, 0xbd, 0xa4, 0xf4, 0x7a, - 0x4d, 0xf7, 0x70, 0x48, 0xc6, 0x9d, 0xe9, 0x23, 0xee, 0x09, 0x6b, 0x26, 0x6e, 0x99, 0x76, 0x66, - 0xf2, 0xb7, 0x32, 0x01, 0xbf, 0x30, 0x6a, 0x28, 0x9f, 0xdf, 0xfa, 0xb4, 0x1e, 0x04, 0xbf, 0xd6, - 0x83, 0x60, 0xf4, 0x8d, 0xd0, 0xfe, 0x4d, 0x90, 0x68, 0x74, 0x8e, 0xc0, 0x4e, 0xe8, 0x9d, 0x96, - 0x43, 0x5d, 0x32, 0x3c, 0x1c, 0x77, 0xa6, 0x0f, 0xf9, 0x9e, 0x9f, 0x8f, 0x37, 0xc7, 0xcc, 0x8e, - 0x2e, 0x7f, 0x0c, 0x82, 0xa8, 0x3d, 0x81, 0xbd, 0x6a, 0xdd, 0x70, 0x60, 0x6f, 0x78, 0xfc, 0xd7, - 0x1b, 0x1c, 0x4f, 0xf3, 0x88, 0xd1, 0x17, 0x42, 0x99, 0x45, 0x9f, 0x65, 0x7a, 0xf1, 0xe1, 0x7f, - 0x33, 0x76, 0x4d, 0xe8, 0xdd, 0x16, 0x9d, 0x77, 0xf4, 0x05, 0x3d, 0x56, 0xf6, 0xc5, 0x5b, 0x39, - 0xda, 0x6b, 0xe5, 0x3b, 0x84, 0xc2, 0x8a, 0xbd, 0x8f, 0x5e, 0xf7, 0xcf, 0x0c, 0x9c, 0xbd, 0xb9, - 0xdc, 0x84, 0xe4, 0x6a, 0x13, 0x92, 0x9f, 0x9b, 0x90, 0x7c, 0xde, 0x86, 0xc1, 0xd5, 0x36, 0x0c, - 0xbe, 0x6f, 0xc3, 0xe0, 0xfd, 0x24, 0x49, 0xcb, 0xb3, 0x4a, 0xf1, 0x85, 0x5e, 0x0a, 0x87, 0xf7, - 0x34, 0x93, 0x0a, 0x7d, 0x2c, 0x2e, 0xa6, 0xe2, 0xe3, 0xf5, 0x17, 0x55, 0xae, 0x0c, 0xa0, 0x3a, - 0xb6, 0x7f, 0xfa, 0x67, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x72, 0x42, 0x3d, 0x1e, 0x0c, 0x04, - 0x00, 0x00, + 0x10, 0x86, 0xbd, 0x77, 0xd1, 0x09, 0x36, 0xa2, 0x59, 0x90, 0x48, 0x22, 0xe4, 0x44, 0x91, 0x80, + 0x08, 0x89, 0x5d, 0x25, 0x74, 0x54, 0x28, 0x05, 0x08, 0xd1, 0x70, 0x96, 0x68, 0x68, 0xa2, 0xdd, + 0x64, 0xce, 0x67, 0xe1, 0x78, 0xf7, 0x3c, 0xf6, 0x89, 0xbc, 0x01, 0x25, 0x3d, 0x4d, 0xc4, 0x53, + 0xf0, 0x08, 0x57, 0x5e, 0x49, 0x85, 0x50, 0xd2, 0xf0, 0x18, 0xc8, 0xbb, 0x1b, 0xce, 0x96, 0x12, + 0xd1, 0x50, 0xd0, 0xcd, 0xec, 0xcc, 0x3f, 0xf3, 0xcd, 0x9f, 0x98, 0x8e, 0x17, 0x80, 0x4b, 0x8d, + 0xc2, 0xe4, 0xfa, 0x2c, 0x49, 0x01, 0xc5, 0xe5, 0x58, 0x41, 0x21, 0xc7, 0xe2, 0xa2, 0x84, 0x7c, + 0x35, 0xcb, 0x21, 0x95, 0x45, 0xa2, 0x33, 0x3c, 0x4f, 0x0c, 0x72, 0x93, 0xeb, 0x42, 0xb3, 0xfb, + 0x4e, 0xc2, 0x77, 0x12, 0xee, 0x25, 0xbd, 0x7b, 0xb1, 0x8e, 0xb5, 0xed, 0x11, 0x55, 0xe4, 0xda, + 0x7b, 0x0f, 0x62, 0xad, 0xe3, 0x14, 0x84, 0x34, 0x89, 0x90, 0x59, 0xa6, 0x0b, 0x37, 0xd0, 0x57, + 0xbb, 0xbe, 0x6a, 0x33, 0x55, 0x9e, 0x09, 0x99, 0xad, 0x7c, 0x69, 0x72, 0x08, 0x6d, 0xa9, 0x17, + 0x90, 0xe2, 0x3e, 0xb6, 0x5e, 0x77, 0xae, 0x2b, 0xcd, 0xcc, 0x51, 0xb8, 0xc4, 0x97, 0x9e, 0xb8, + 0x4c, 0x28, 0x89, 0xe0, 0xae, 0xfb, 0x33, 0xd0, 0xc8, 0x38, 0xc9, 0xec, 0x2c, 0xd7, 0x3b, 0xfc, + 0x4a, 0x68, 0xf7, 0xb4, 0x6a, 0x89, 0xea, 0x3b, 0x22, 0xb8, 0x28, 0x01, 0x0b, 0xc6, 0x68, 0xab, + 0x44, 0xc8, 0x3b, 0x64, 0x40, 0x46, 0xb7, 0x23, 0x1b, 0xb3, 0x3e, 0x6d, 0x63, 0xa9, 0xd0, 0xc8, + 0x39, 0xcc, 0x92, 0x45, 0xe7, 0x68, 0x40, 0x46, 0xad, 0x88, 0xee, 0x9e, 0x5e, 0x2f, 0xd8, 0x4b, + 0x4a, 0x6f, 0xd6, 0x74, 0x8e, 0x07, 0x64, 0xd4, 0x9e, 0x3c, 0xe2, 0x9e, 0xb0, 0x62, 0xe2, 0x96, + 0x69, 0x67, 0x26, 0x7f, 0x2b, 0x63, 0xf0, 0x0b, 0xa3, 0x9a, 0xf2, 0xf9, 0xad, 0x4f, 0xeb, 0x7e, + 0xf0, 0x6b, 0xdd, 0x0f, 0x86, 0xdf, 0x08, 0xed, 0xed, 0x83, 0x44, 0xa3, 0x33, 0x04, 0x76, 0x4a, + 0xef, 0x34, 0x1c, 0xea, 0x90, 0xc1, 0xf1, 0xa8, 0x3d, 0x79, 0xc8, 0x0f, 0xfc, 0x7c, 0xbc, 0x3e, + 0x66, 0xda, 0xba, 0xfa, 0xd1, 0x0f, 0xa2, 0xe6, 0x04, 0xf6, 0xaa, 0x71, 0xc3, 0x91, 0xbd, 0xe1, + 0xf1, 0x5f, 0x6f, 0x70, 0x3c, 0xf5, 0x23, 0x86, 0x5f, 0x08, 0x65, 0x16, 0x7d, 0x9a, 0xea, 0xf9, + 0x87, 0xff, 0xcd, 0xd8, 0x35, 0xa1, 0x77, 0x1b, 0x74, 0xde, 0xd1, 0x17, 0xf4, 0x44, 0xd9, 0x17, + 0x6f, 0xe5, 0xf0, 0xa0, 0x95, 0xef, 0x10, 0x72, 0x2b, 0xf6, 0x3e, 0x7a, 0xdd, 0x3f, 0x33, 0x70, + 0xfa, 0xe6, 0x6a, 0x13, 0x92, 0xeb, 0x4d, 0x48, 0x7e, 0x6e, 0x42, 0xf2, 0x79, 0x1b, 0x06, 0xd7, + 0xdb, 0x30, 0xf8, 0xbe, 0x0d, 0x83, 0xf7, 0xe3, 0x38, 0x29, 0xce, 0x4b, 0xc5, 0xe7, 0x7a, 0x29, + 0x1c, 0xde, 0xd3, 0x54, 0x2a, 0xf4, 0xb1, 0xb8, 0x9c, 0x88, 0x8f, 0x37, 0x5f, 0x54, 0xb1, 0x32, + 0x80, 0xea, 0xc4, 0xfe, 0xe9, 0x9f, 0xfd, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x9b, 0x95, 0x8e, 0x67, + 0x0c, 0x04, 0x00, 0x00, } func (m *QueryRelationshipsRequest) Marshal() (dAtA []byte, err error) { @@ -298,12 +298,10 @@ func (m *QueryRelationshipsRequest) MarshalToSizedBuffer(dAtA []byte) (int, erro i-- dAtA[i] = 0x1a } - if len(m.SubspaceId) > 0 { - i -= len(m.SubspaceId) - copy(dAtA[i:], m.SubspaceId) - i = encodeVarintQueryRelationships(dAtA, i, uint64(len(m.SubspaceId))) + if m.SubspaceId != 0 { + i = encodeVarintQueryRelationships(dAtA, i, uint64(m.SubspaceId)) i-- - dAtA[i] = 0x12 + dAtA[i] = 0x10 } if len(m.User) > 0 { i -= len(m.User) @@ -396,12 +394,10 @@ func (m *QueryBlocksRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x1a } - if len(m.SubspaceId) > 0 { - i -= len(m.SubspaceId) - copy(dAtA[i:], m.SubspaceId) - i = encodeVarintQueryRelationships(dAtA, i, uint64(len(m.SubspaceId))) + if m.SubspaceId != 0 { + i = encodeVarintQueryRelationships(dAtA, i, uint64(m.SubspaceId)) i-- - dAtA[i] = 0x12 + dAtA[i] = 0x10 } if len(m.User) > 0 { i -= len(m.User) @@ -483,9 +479,8 @@ func (m *QueryRelationshipsRequest) Size() (n int) { if l > 0 { n += 1 + l + sovQueryRelationships(uint64(l)) } - l = len(m.SubspaceId) - if l > 0 { - n += 1 + l + sovQueryRelationships(uint64(l)) + if m.SubspaceId != 0 { + n += 1 + sovQueryRelationships(uint64(m.SubspaceId)) } if m.Pagination != nil { l = m.Pagination.Size() @@ -523,9 +518,8 @@ func (m *QueryBlocksRequest) Size() (n int) { if l > 0 { n += 1 + l + sovQueryRelationships(uint64(l)) } - l = len(m.SubspaceId) - if l > 0 { - n += 1 + l + sovQueryRelationships(uint64(l)) + if m.SubspaceId != 0 { + n += 1 + sovQueryRelationships(uint64(m.SubspaceId)) } if m.Pagination != nil { l = m.Pagination.Size() @@ -621,10 +615,10 @@ func (m *QueryRelationshipsRequest) Unmarshal(dAtA []byte) error { m.User = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: - if wireType != 2 { + if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field SubspaceId", wireType) } - var stringLen uint64 + m.SubspaceId = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQueryRelationships @@ -634,24 +628,11 @@ func (m *QueryRelationshipsRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.SubspaceId |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthQueryRelationships - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQueryRelationships - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SubspaceId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) @@ -891,10 +872,10 @@ func (m *QueryBlocksRequest) Unmarshal(dAtA []byte) error { m.User = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: - if wireType != 2 { + if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field SubspaceId", wireType) } - var stringLen uint64 + m.SubspaceId = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQueryRelationships @@ -904,24 +885,11 @@ func (m *QueryBlocksRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.SubspaceId |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthQueryRelationships - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQueryRelationships - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SubspaceId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) diff --git a/x/subspaces/client/cli/cli_test.go b/x/subspaces/client/cli/cli_test.go new file mode 100644 index 0000000000..cdd9f35b35 --- /dev/null +++ b/x/subspaces/client/cli/cli_test.go @@ -0,0 +1,859 @@ +package cli_test + +import ( + "fmt" + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/gogo/protobuf/proto" + + "github.com/desmos-labs/desmos/v2/x/subspaces/client/cli" + + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + "github.com/stretchr/testify/suite" + tmcli "github.com/tendermint/tendermint/libs/cli" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/testutil" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := testutil.DefaultConfig() + genesisState := cfg.GenesisState + cfg.NumValidators = 2 + + // Initialize the module genesis data + genesis := types.NewGenesisState( + 3, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + types.NewGenesisSubspace( + types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + ), + 3, + ), + types.NewGenesisSubspace( + types.NewSubspace( + 3, + "Subspace to delete", + "This is a test subspace that will be deleted", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + []types.ACLEntry{ + types.NewACLEntry(1, "cosmos1xw69y2z3yf00rgfnly99628gn5c0x7fryyfv5e", types.PermissionWrite), + types.NewACLEntry(2, "cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd", types.PermissionManageGroups), + }, + []types.UserGroup{ + types.NewUserGroup(1, 1, "Test group", "", types.PermissionWrite), + types.NewUserGroup(2, 1, "Another test group", "", types.PermissionManageGroups), + types.NewUserGroup(2, 2, "Third group", "", types.PermissionWrite), + }, + []types.UserGroupMembersEntry{ + types.NewUserGroupMembersEntry(1, 1, []string{ + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + }), + types.NewUserGroupMembersEntry(2, 1, []string{ + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + }), + }, + ) + + // Store the genesis data + subspacesDataBz, err := cfg.Codec.MarshalJSON(genesis) + s.Require().NoError(err) + genesisState[types.ModuleName] = subspacesDataBz + cfg.GenesisState = genesisState + + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +// -------------------------------------------------------------------------------------------------------------------- + +func (s *IntegrationTestSuite) TestCmdQuerySubspace() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + expResponse types.QuerySubspaceResponse + }{ + { + name: "non existing subspace returns error", + args: []string{ + "10", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + shouldErr: true, + }, + { + name: "existing subspace is returned correctly", + args: []string{ + "1", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + shouldErr: false, + expResponse: types.QuerySubspaceResponse{ + Subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQuerySubspace() + clientCtx := val.ClientCtx + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + + var response types.QuerySubspaceResponse + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(response.Subspace, tc.expResponse.Subspace) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdQuerySubspaces() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + expResponse types.QuerySubspacesResponse + }{ + { + name: "subspaces are returned correctly", + args: []string{ + fmt.Sprintf("--%s=%d", flags.FlagLimit, 1), + fmt.Sprintf("--%s=%d", flags.FlagPage, 1), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + shouldErr: false, + expResponse: types.QuerySubspacesResponse{ + Subspaces: []types.Subspace{ + types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQuerySubspaces() + clientCtx := val.ClientCtx + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + + var response types.QuerySubspacesResponse + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expResponse.Subspaces, response.Subspaces) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdQueryUserGroups() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + expResponse types.QueryUserGroupsResponse + }{ + { + name: "user groups are returned correctly", + args: []string{ + "2", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + shouldErr: false, + expResponse: types.QueryUserGroupsResponse{ + Groups: []types.UserGroup{ + types.NewUserGroup(2, 1, "Another test group", "", types.PermissionManageGroups), + types.NewUserGroup(2, 2, "Third group", "", types.PermissionWrite), + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryUserGroups() + clientCtx := val.ClientCtx + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + + var response types.QueryUserGroupsResponse + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expResponse.Groups, response.Groups) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdQueryUserGroupMembers() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + expResponse types.QueryUserGroupMembersResponse + }{ + { + name: "subspace not found returns error", + args: []string{"10", "1"}, + shouldErr: true, + }, + { + name: "group not found returns error", + args: []string{"1", "10"}, + shouldErr: true, + }, + { + name: "members are returned correctly", + args: []string{ + "2", "1", + fmt.Sprintf("--%s=%d", flags.FlagLimit, 1), + fmt.Sprintf("--%s=%d", flags.FlagPage, 1), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + shouldErr: false, + expResponse: types.QueryUserGroupMembersResponse{ + Members: []string{ + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryUserGroupMembers() + clientCtx := val.ClientCtx + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + + var response types.QueryUserGroupMembersResponse + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expResponse.Members, response.Members) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdCreateSubspace() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + expErr bool + respType proto.Message + }{ + { + name: "invalid name returns error", + args: []string{ + "", + }, + expErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "Test subspace", + fmt.Sprintf("--%s=%s", cli.FlagDescription, "This is a test subspace"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + expErr: false, + respType: &sdk.TxResponse{}, + }, + { + name: "valid data returns no error with custom treasury and owner", + args: []string{ + "Another test subspace", + fmt.Sprintf("--%s=%s", cli.FlagDescription, "Another test subspace"), + fmt.Sprintf("--%s=%s", cli.FlagTreasury, "cosmos1lqjd4p6uxvsvus6kf3gf00uz7luj4jcxpyahul"), + fmt.Sprintf("--%s=%s", cli.FlagOwner, "cosmos1et50whs236j9dacacz7feh05jjum9jk04cdt9u"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + expErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdCreateSubspace() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdEditSubspace() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{"subspace"}, + shouldErr: true, + }, + { + name: "invalid name returns error", + args: []string{ + "1", + fmt.Sprintf("--%s=%s", cli.FlagName, ""), + }, + shouldErr: true, + }, + { + name: "invalid owner flag returns error", + args: []string{ + "1", + fmt.Sprintf("--%s=%s", cli.FlagOwner, "abd"), + }, + shouldErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "2", + fmt.Sprintf("--%s=%s", cli.FlagName, "Edited name"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdEditSubspace() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdDeleteSubspace() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{"subspace"}, + shouldErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "3", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdDeleteSubspace() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdCreateUserGroup() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{"id", "testing-group"}, + shouldErr: true, + }, + { + name: "invalid name returns error", + args: []string{"1", ""}, + shouldErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "2", "testing-group", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdCreateUserGroup() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdEditUserGroup() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{"0", "1"}, + shouldErr: true, + }, + { + name: "invalid group id returns error", + args: []string{"1", "0"}, + shouldErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "1", "1", + fmt.Sprintf("--%s=%s", flags.FlagName, "This is my new group name"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdEditUserGroup() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdSetUserGroupPermissions() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{"0", "1"}, + shouldErr: true, + }, + { + name: "invalid group id returns error", + args: []string{"1", "0"}, + shouldErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "1", "1", types.SerializePermission(types.PermissionWrite), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdSetUserGroupPermissions() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdDeleteUserGroup() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{"subspace-id", "testing-group"}, + shouldErr: true, + }, + { + name: "invalid name returns error", + args: []string{"1", ""}, + shouldErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "2", "1", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdDeleteUserGroup() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdAddUserToUserGroup() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{"subspace-id", "testing-group"}, + shouldErr: true, + }, + { + name: "invalid name returns error", + args: []string{"1", ""}, + shouldErr: true, + }, + { + name: "invalid user returns error", + args: []string{"1", "1", ""}, + shouldErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "2", "1", "cosmos1et50whs236j9dacacz7feh05jjum9jk04cdt9u", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdAddUserToUserGroup() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdRemoveUserFromUserGroup() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{"subspace-id", "testing-group"}, + shouldErr: true, + }, + { + name: "invalid name returns error", + args: []string{"1", ""}, + shouldErr: true, + }, + { + name: "invalid user returns error", + args: []string{"1", "group", ""}, + shouldErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "2", "1", "cosmos1et50whs236j9dacacz7feh05jjum9jk04cdt9u", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdRemoveUserFromUserGroup() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdSetPermissions() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{"id", "group", "Write"}, + shouldErr: true, + }, + { + name: "invalid target returns error", + args: []string{"1", "", "Write"}, + shouldErr: true, + }, + { + name: "invalid permission returns error", + args: []string{"1", "group", "NonExistingPermission"}, + shouldErr: true, + }, + { + name: "valid data returns no error", + args: []string{ + "1", "cosmos1xw69y2z3yf00rgfnly99628gn5c0x7fryyfv5e", "Write", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdSetUserPermissions() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} diff --git a/x/subspaces/client/cli/query.go b/x/subspaces/client/cli/query.go new file mode 100644 index 0000000000..17559f89df --- /dev/null +++ b/x/subspaces/client/cli/query.go @@ -0,0 +1,214 @@ +package cli + +import ( + "context" + "fmt" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/version" + "github.com/spf13/cobra" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// DONTCOVER + +// GetQueryCmd returns the command allowing to perform queries +func GetQueryCmd() *cobra.Command { + subspaceQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the subspaces module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + subspaceQueryCmd.AddCommand( + GetCmdQuerySubspace(), + GetCmdQuerySubspaces(), + + GetGroupsQueryCmd(), + ) + return subspaceQueryCmd +} + +// GetCmdQuerySubspace returns the command to query the subspace with the given id +func GetCmdQuerySubspace() *cobra.Command { + cmd := &cobra.Command{ + Use: "subspace [id]", + Short: "Query the subspace with the given id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + res, err := queryClient.Subspace(context.Background(), types.NewQuerySubspaceRequest(subspaceID)) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQuerySubspaces returns the command to query all the subspaces +func GetCmdQuerySubspaces() *cobra.Command { + cmd := &cobra.Command{ + Use: "subspaces", + Short: "Query subspaces with optional pagination", + Example: fmt.Sprintf(` +%s query subspaces subspaces --page=2 --limit=100`, + version.AppName), + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + res, err := queryClient.Subspaces(context.Background(), types.NewQuerySubspacesRequest(pageReq)) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "subspaces") + + return cmd +} + +// ------------------------------------------------------------------------------------------------------------------- + +// GetGroupsQueryCmd returns a new command to perform queries for user groups +func GetGroupsQueryCmd() *cobra.Command { + groupsQueryCmd := &cobra.Command{ + Use: "groups", + Short: "Querying commands for subspace groups", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + groupsQueryCmd.AddCommand( + GetCmdQueryUserGroups(), + GetCmdQueryUserGroupMembers(), + ) + + return groupsQueryCmd +} + +// GetCmdQueryUserGroups returns the command to query the user groups of a subspace +func GetCmdQueryUserGroups() *cobra.Command { + cmd := &cobra.Command{ + Use: "list [subspace-id]", + Short: "Query subspaces with optional pagination", + Example: fmt.Sprintf(` +%s query subspaces user-groups 1 --page=2 --limit=100`, + version.AppName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + res, err := queryClient.UserGroups( + context.Background(), + types.NewQueryUserGroupsRequest(subspaceID, pageReq), + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "user groups") + + return cmd +} + +// GetCmdQueryUserGroupMembers returns the command to query the members of a specific user group +func GetCmdQueryUserGroupMembers() *cobra.Command { + cmd := &cobra.Command{ + Use: "members [subspace-id] [group-id]", + Short: "Query subspaces with optional pagination", + Example: fmt.Sprintf(` +%s query subspaces user-group-members 1 1 --page=2 --limit=100`, + version.AppName), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + groupID, err := types.ParseGroupID(args[1]) + if err != nil { + return err + } + + res, err := queryClient.UserGroupMembers( + context.Background(), + types.NewQueryUserGroupMembersRequest(subspaceID, groupID, pageReq), + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "user group members") + + return cmd +} diff --git a/x/subspaces/client/cli/tx.go b/x/subspaces/client/cli/tx.go new file mode 100644 index 0000000000..e546d7f7f3 --- /dev/null +++ b/x/subspaces/client/cli/tx.go @@ -0,0 +1,570 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/version" + "github.com/spf13/cobra" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// DONTCOVER + +const ( + FlagName = "name" + FlagDescription = "description" + FlagTreasury = "treasury" + FlagOwner = "owner" + FlagPermissions = "permissions" +) + +// NewTxCmd returns a new command to perform subspaces transactions +func NewTxCmd() *cobra.Command { + subspacesTxCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Subspaces transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + subspacesTxCmd.AddCommand( + GetCmdCreateSubspace(), + GetCmdEditSubspace(), + + NewGroupsTxCmd(), + + GetCmdSetUserPermissions(), + ) + + return subspacesTxCmd +} + +// GetCmdCreateSubspace returns the command used to create a subspace +func GetCmdCreateSubspace() *cobra.Command { + cmd := &cobra.Command{ + Use: "create [name]", + Args: cobra.ExactArgs(1), + Short: "Create a new subspace", + Long: `Create a new subspace. +The name must be a human readable name.`, + Example: fmt.Sprintf(` +%s tx subspaces create "Desmos" \ + --description "The official subspace of Desmos" \ + --treasury desmos1jqk5p244yl4ktukq5xhavvlfzl8z4we4qfmuyh \ + --owner desmos1p8r4guvdze03md4g9zclhh6mr8ljvtd80pehr3 \ + --from alice +`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + name := args[0] + + description, err := cmd.Flags().GetString(FlagDescription) + if err != nil { + return err + } + + treasury, err := cmd.Flags().GetString(FlagTreasury) + if err != nil { + return err + } + + owner, err := cmd.Flags().GetString(FlagOwner) + if err != nil { + return err + } + + msg := types.NewMsgCreateSubspace(name, description, treasury, owner, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(FlagDescription, "", "Description of the subspace") + cmd.Flags().String(FlagTreasury, "", "Treasury of the subspace") + cmd.Flags().String(FlagOwner, "", "Owner of the subspace") + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdEditSubspace returns the command to edit a subspace +func GetCmdEditSubspace() *cobra.Command { + cmd := &cobra.Command{ + Use: "edit [subspace-id]", + Args: cobra.ExactArgs(1), + Short: "Edit the subspace with the given id", + Example: fmt.Sprintf(` +%s tx subspaces edit 1 \ + --name "Desmos - Democratizing social networks" + --description "The official subspace of Desmos" \ + --treasury desmos1jqk5p244yl4ktukq5xhavvlfzl8z4we4qfmuyh \ + --owner desmos1p8r4guvdze03md4g9zclhh6mr8ljvtd80pehr3 \ + --from alice +`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + name, err := cmd.Flags().GetString(FlagName) + if err != nil { + return err + } + + description, err := cmd.Flags().GetString(FlagDescription) + if err != nil { + return err + } + + treasury, err := cmd.Flags().GetString(FlagTreasury) + if err != nil { + return err + } + + owner, err := cmd.Flags().GetString(FlagOwner) + if err != nil { + return err + } + + msg := types.NewMsgEditSubspace(subspaceID, name, description, treasury, owner, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(FlagName, types.DoNotModify, "New human readable name of the subspace") + cmd.Flags().String(FlagDescription, types.DoNotModify, "Description of the subspace") + cmd.Flags().String(FlagTreasury, types.DoNotModify, "Treasury of the subspace") + cmd.Flags().String(FlagOwner, types.DoNotModify, "Owner of the subspace") + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdDeleteSubspace returns the command to delete a subspace +func GetCmdDeleteSubspace() *cobra.Command { + cmd := &cobra.Command{ + Use: "delete [subspace-id]", + Args: cobra.ExactArgs(1), + Short: "Deletes the subspace with the given id", + Example: fmt.Sprintf(`%s tx subspaces delete 1 --from alice`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + msg := types.NewMsgDeleteSubspace(subspaceID, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// ------------------------------------------------------------------------------------------------------------------- + +// NewGroupsTxCmd returns a new command to perform subspaces groups transactions +func NewGroupsTxCmd() *cobra.Command { + groupsTxCmd := &cobra.Command{ + Use: "groups", + Short: "Subspace groups transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + groupsTxCmd.AddCommand( + GetCmdCreateUserGroup(), + GetCmdEditUserGroup(), + GetCmdSetUserGroupPermissions(), + GetCmdDeleteUserGroup(), + GetCmdAddUserToUserGroup(), + GetCmdRemoveUserFromUserGroup(), + ) + + return groupsTxCmd +} + +// GetCmdCreateUserGroup returns the command to create a user group +func GetCmdCreateUserGroup() *cobra.Command { + cmd := &cobra.Command{ + Use: "create [subspace-id] [group-name] [[permissions]]", + Args: cobra.MinimumNArgs(2), + Short: "Create a new user group within a subspace", + Long: fmt.Sprintf(`Create a new user group within the subspace having the provided id. + +An optional description of this group can be provided with the %[1]s flag. + +The permissions of this group can be set using the %[2]s flag. +If no permissions are set, the default PermissionNothing will be used instead. +Multiple permissions must be specified separating them with a comma (,).`, FlagDescription, FlagPermissions), + Example: fmt.Sprintf(` +%s tx subspaces groups create-user-group 1 "Admins" \ + --description "Group of the subspace admins" \ + --permissions "Write,ModerateContent,SetUserPermissions" \ + --from alice +`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + name := args[1] + + description, err := cmd.Flags().GetString(FlagDescription) + if err != nil { + return err + } + + permissions, err := cmd.Flags().GetStringSlice(FlagPermissions) + if err != nil { + return err + } + + permission := types.PermissionNothing + for _, permArg := range permissions { + perm, err := types.ParsePermission(permArg) + if err != nil { + return err + } + permission = types.CombinePermissions(permission, perm) + } + + msg := types.NewMsgCreateUserGroup(subspaceID, name, description, permission, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(FlagDescription, "", "Description of the group") + cmd.Flags().StringSlice(FlagPermissions, []string{types.SerializePermission(types.PermissionNothing)}, "Permissions of the group") + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdEditUserGroup returns the command to edit a user group +func GetCmdEditUserGroup() *cobra.Command { + cmd := &cobra.Command{ + Use: "edit [subspace-id] [group-id]", + Args: cobra.ExactArgs(2), + Short: "Edit the group with the given id", + Example: fmt.Sprintf(` +%s tx subspaces groups edit 1 1 \ + --name "Super admins" + --description "This is the group of super users" \ + --from alice +`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + groupID, err := types.ParseGroupID(args[1]) + if err != nil { + return err + } + + name, err := cmd.Flags().GetString(FlagName) + if err != nil { + return err + } + + description, err := cmd.Flags().GetString(FlagDescription) + if err != nil { + return err + } + + msg := types.NewMsgEditUserGroup(subspaceID, groupID, name, description, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(FlagName, types.DoNotModify, "New human readable name of the group") + cmd.Flags().String(FlagDescription, types.DoNotModify, "Description of the group") + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdSetUserGroupPermissions returns the command to set the permissions for a user group +func GetCmdSetUserGroupPermissions() *cobra.Command { + cmd := &cobra.Command{ + Use: "set-permissions [subspace-id] [group-id] [permissions]", + Args: cobra.ExactArgs(3), + Short: "Set the permissions for a specific group", + Long: `Set the permissions for a specific user group a given subspace. +It is mandatory to specify at least one permission to be set. +When specifying multiple permissions, they must be separated by a comma (,).`, + Example: fmt.Sprintf(` +%s tx subspaces groups set-permissions 1 1 "Write,ModerateContent,SetUserPermissions" \ + --from alice +`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + groupID, err := types.ParseGroupID(args[1]) + if err != nil { + return err + } + + permission := types.PermissionNothing + for _, arg := range strings.Split(args[2], ",") { + perm, err := types.ParsePermission(arg) + if err != nil { + return err + } + permission = types.CombinePermissions(permission, perm) + } + + msg := types.NewMsgSetUserGroupPermissions(subspaceID, groupID, permission, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdDeleteUserGroup returns the command to delete a user group +func GetCmdDeleteUserGroup() *cobra.Command { + cmd := &cobra.Command{ + Use: "delete [subspace-id] [group-id]", + Args: cobra.ExactArgs(2), + Short: "Delete a user group from a subspace", + Example: fmt.Sprintf(` +%s tx subspaces groups delete-user-group 1 1 --from alice +`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + groupID, err := types.ParseGroupID(args[1]) + if err != nil { + return err + } + + msg := types.NewMsgDeleteUserGroup(subspaceID, groupID, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdAddUserToUserGroup returns the command to add a user to a user group +func GetCmdAddUserToUserGroup() *cobra.Command { + cmd := &cobra.Command{ + Use: "add-user [subspace-id] [group-id] [user]", + Args: cobra.ExactArgs(3), + Short: "Add a user to a user group", + Example: fmt.Sprintf(` +%s tx subspaces groups add-user-to-user-group 1 1 desmos1p8r4guvdze03md4g9zclhh6mr8ljvtd80pehr3 \ + --from alice +`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + groupID, err := types.ParseGroupID(args[1]) + if err != nil { + return err + } + + user := args[2] + + msg := types.NewMsgAddUserToUserGroup(subspaceID, groupID, user, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdRemoveUserFromUserGroup returns the command to remove a user from a user group +func GetCmdRemoveUserFromUserGroup() *cobra.Command { + cmd := &cobra.Command{ + Use: "remove-user [subspace-id] [group-id] [user]", + Args: cobra.ExactArgs(3), + Short: "Remove a user from a user group", + Example: fmt.Sprintf(` +%s tx subspaces groups remove-user-from-user-group 1 1 desmos1p8r4guvdze03md4g9zclhh6mr8ljvtd80pehr3 \ + --from alice +`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + groupID, err := types.ParseGroupID(args[1]) + if err != nil { + return err + } + + user := args[2] + + msg := types.NewMsgRemoveUserFromUserGroup(subspaceID, groupID, user, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// -------------------------------------------------------------------------------------------------------------------- + +// GetCmdSetUserPermissions returns the command to set the permissions for a user +func GetCmdSetUserPermissions() *cobra.Command { + cmd := &cobra.Command{ + Use: "set-user-permissions [subspace-id] [user] [permissions]", + Args: cobra.ExactArgs(3), + Short: "Set the permissions for a specific user", + Long: `Set the permissions for a specific user inside a given subspace. +It is mandatory to specify at least one permission to be set. +When specifying multiple permissions, they must be separated by a comma (,).`, + Example: fmt.Sprintf(` +%s tx subspaces sset-user-permissions 1 desmos1463vltcqk6ql6zpk0g6s595jjcrzk4804hyqw7 "Write,ModerateContent,SetUserPermissions" \ + --from alice +`, version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := types.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + user := args[1] + + permission := types.PermissionNothing + for _, arg := range strings.Split(args[2], ",") { + perm, err := types.ParsePermission(arg) + if err != nil { + return err + } + permission = types.CombinePermissions(permission, perm) + } + + msg := types.NewMsgSetUserPermissions(subspaceID, user, permission, clientCtx.FromAddress.String()) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/subspaces/handler.go b/x/subspaces/handler.go new file mode 100644 index 0000000000..bae2683cdc --- /dev/null +++ b/x/subspaces/handler.go @@ -0,0 +1,53 @@ +package subspaces + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/gogo/protobuf/proto" + + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// NewHandler returns a handler for subspaces type messages +func NewHandler(k keeper.Keeper) sdk.Handler { + msgServer := keeper.NewMsgServerImpl(k) + + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + ctx = ctx.WithEventManager(sdk.NewEventManager()) + + switch msg := msg.(type) { + case *types.MsgCreateSubspace: + res, err := msgServer.CreateSubspace(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgEditSubspace: + res, err := msgServer.EditSubspace(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgCreateUserGroup: + res, err := msgServer.CreateUserGroup(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgEditUserGroup: + res, err := msgServer.EditUserGroup(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgSetUserGroupPermissions: + res, err := msgServer.SetUserGroupPermissions(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgDeleteUserGroup: + res, err := msgServer.DeleteUserGroup(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgAddUserToUserGroup: + res, err := msgServer.AddUserToUserGroup(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgRemoveUserFromUserGroup: + res, err := msgServer.RemoveUserFromUserGroup(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgSetUserPermissions: + res, err := msgServer.SetUserPermissions(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + + default: + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, + "unrecognized %s message type: %v", types.ModuleName, proto.MessageName(msg)) + } + } +} diff --git a/x/subspaces/keeper/alias_functions.go b/x/subspaces/keeper/alias_functions.go new file mode 100644 index 0000000000..b66d119103 --- /dev/null +++ b/x/subspaces/keeper/alias_functions.go @@ -0,0 +1,145 @@ +package keeper + +import ( + "bytes" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// IterateSubspaces iterates through the subspaces set and performs the given function +func (k Keeper) IterateSubspaces(ctx sdk.Context, fn func(index int64, subspace types.Subspace) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, types.SubspacePrefix) + defer iterator.Close() + + i := int64(0) + for ; iterator.Valid(); iterator.Next() { + var subspace types.Subspace + k.cdc.MustUnmarshal(iterator.Value(), &subspace) + stop := fn(i, subspace) + if stop { + break + } + i++ + } +} + +// GetAllSubspaces returns a list of all the subspaces that have been store inside the given context +func (k Keeper) GetAllSubspaces(ctx sdk.Context) []types.Subspace { + var subspaces []types.Subspace + k.IterateSubspaces(ctx, func(_ int64, subspace types.Subspace) (stop bool) { + subspaces = append(subspaces, subspace) + return false + }) + + return subspaces +} + +// -------------------------------------------------------------------------------------------------------------------- + +// IterateUserGroups iterates over all the users groups stored +func (k Keeper) IterateUserGroups(ctx sdk.Context, fn func(index int64, group types.UserGroup) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, types.GroupsPrefix) + defer iterator.Close() + + i := int64(0) + for ; iterator.Valid(); iterator.Next() { + var group types.UserGroup + k.cdc.MustUnmarshal(iterator.Value(), &group) + stop := fn(i, group) + if stop { + break + } + i++ + } +} + +// IterateSubspaceGroups allows iterating over all the groups that are part of the subspace having the given id +func (k Keeper) IterateSubspaceGroups( + ctx sdk.Context, subspaceID uint64, fn func(index int64, group types.UserGroup) (stop bool), +) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, types.GroupsStoreKey(subspaceID)) + defer iterator.Close() + + i := int64(0) + for ; iterator.Valid(); iterator.Next() { + var group types.UserGroup + k.cdc.MustUnmarshal(iterator.Value(), &group) + stop := fn(i, group) + if stop { + break + } + i++ + } +} + +// GetSubspaceGroups returns the list of all groups present inside a given subspace +func (k Keeper) GetSubspaceGroups(ctx sdk.Context, subspaceID uint64) []types.UserGroup { + var groups []types.UserGroup + k.IterateSubspaceGroups(ctx, subspaceID, func(index int64, group types.UserGroup) (stop bool) { + groups = append(groups, group) + return false + }) + return groups +} + +// IterateGroupMembers iterates over all the members of the group with the given name present inside the given subspace +func (k Keeper) IterateGroupMembers( + ctx sdk.Context, subspaceID uint64, groupID uint32, fn func(index int64, member sdk.AccAddress) (stop bool), +) { + store := ctx.KVStore(k.storeKey) + + prefix := types.GroupMembersStoreKey(subspaceID, groupID) + iterator := sdk.KVStorePrefixIterator(store, prefix) + defer iterator.Close() + + i := int64(0) + for ; iterator.Valid(); iterator.Next() { + member := types.GetAddressFromBytes(bytes.TrimPrefix(iterator.Key(), prefix)) + + stop := fn(i, member) + if stop { + break + } + i++ + } +} + +// GetGroupMembers iterates returns all the members of a group inside a specific subspace +func (k Keeper) GetGroupMembers(ctx sdk.Context, subspaceID uint64, groupID uint32) []sdk.AccAddress { + var members []sdk.AccAddress + k.IterateGroupMembers(ctx, subspaceID, groupID, func(index int64, member sdk.AccAddress) (stop bool) { + members = append(members, member) + return false + }) + return members +} + +// -------------------------------------------------------------------------------------------------------------------- + +// IterateSubspacePermissions iterates over all the permissions set for the subspace with the given id +func (k Keeper) IterateSubspacePermissions( + ctx sdk.Context, subspaceID uint64, fn func(index int64, user sdk.AccAddress, permission types.Permission) (stop bool), +) { + store := ctx.KVStore(k.storeKey) + + prefix := types.PermissionsStoreKey(subspaceID) + iterator := sdk.KVStorePrefixIterator(store, prefix) + defer iterator.Close() + + i := int64(0) + for ; iterator.Valid(); iterator.Next() { + user := types.GetAddressFromBytes(bytes.TrimPrefix(iterator.Key(), prefix)) + permission := types.UnmarshalPermission(iterator.Value()) + + stop := fn(i, user, permission) + if stop { + break + } + i++ + } +} diff --git a/x/subspaces/keeper/common_test.go b/x/subspaces/keeper/common_test.go new file mode 100644 index 0000000000..aadb4fc4a0 --- /dev/null +++ b/x/subspaces/keeper/common_test.go @@ -0,0 +1,59 @@ +package keeper_test + +import ( + "testing" + + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" + paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/stretchr/testify/suite" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + db "github.com/tendermint/tm-db" + + "github.com/desmos-labs/desmos/v2/app" +) + +type KeeperTestsuite struct { + suite.Suite + + cdc codec.Codec + legacyAminoCdc *codec.LegacyAmino + ctx sdk.Context + k keeper.Keeper + paramsKeeper paramskeeper.Keeper + storeKey sdk.StoreKey +} + +func (suite *KeeperTestsuite) SetupTest() { + // Define store keys + keys := sdk.NewMemoryStoreKeys(types.StoreKey, paramstypes.StoreKey) + + suite.storeKey = keys[types.StoreKey] + + // Create an in-memory db + memDB := db.NewMemDB() + ms := store.NewCommitMultiStore(memDB) + for _, key := range keys { + ms.MountStoreWithDB(key, sdk.StoreTypeIAVL, memDB) + } + + if err := ms.LoadLatestVersion(); err != nil { + panic(err) + } + + suite.ctx = sdk.NewContext(ms, tmproto.Header{ChainID: "test-chain"}, false, log.NewNopLogger()) + suite.cdc, suite.legacyAminoCdc = app.MakeCodecs() + + // Define keeper + suite.k = keeper.NewKeeper(suite.cdc, suite.storeKey) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestsuite)) +} diff --git a/x/subspaces/keeper/genesis.go b/x/subspaces/keeper/genesis.go new file mode 100644 index 0000000000..01e57e08c7 --- /dev/null +++ b/x/subspaces/keeper/genesis.go @@ -0,0 +1,132 @@ +package keeper + +import ( + "fmt" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// ExportGenesis returns the GenesisState associated with the given context +func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { + subspaceID, err := k.GetSubspaceID(ctx) + if err != nil { + panic(err) + } + + return types.NewGenesisState( + subspaceID, + k.GetGenesisSubspaces(ctx, k.GetAllSubspaces(ctx)), + k.GetAllPermissions(ctx), + k.GetAllUserGroups(ctx), + k.GetUserAllGroupsMembers(ctx), + ) +} + +// GetGenesisSubspaces maps the given subspaces to the corresponding GenesisSubspace instance +func (k Keeper) GetGenesisSubspaces(ctx sdk.Context, subspaces []types.Subspace) []types.GenesisSubspace { + if subspaces == nil { + return nil + } + + genesisSubspaces := make([]types.GenesisSubspace, len(subspaces)) + for i, subspace := range subspaces { + groupID, err := k.GetGroupID(ctx, subspace.ID) + if err != nil { + panic(err) + } + + genesisSubspaces[i] = types.NewGenesisSubspace(subspace, groupID) + } + return genesisSubspaces +} + +// GetAllPermissions returns all the stored permissions for all subspaces +func (k Keeper) GetAllPermissions(ctx sdk.Context) []types.ACLEntry { + var entries []types.ACLEntry + k.IterateSubspaces(ctx, func(index int64, subspace types.Subspace) (stop bool) { + k.IterateSubspacePermissions(ctx, subspace.ID, func(index int64, user sdk.AccAddress, permission types.Permission) (stop bool) { + entries = append(entries, types.NewACLEntry(subspace.ID, user.String(), permission)) + return false + }) + return false + }) + return entries +} + +// GetAllUserGroups returns the information (name and members) for all the groups of all the subspaces +func (k Keeper) GetAllUserGroups(ctx sdk.Context) []types.UserGroup { + var groups []types.UserGroup + k.IterateSubspaces(ctx, func(index int64, subspace types.Subspace) (stop bool) { + k.IterateSubspaceGroups(ctx, subspace.ID, func(index int64, group types.UserGroup) (stop bool) { + groups = append(groups, group) + return false + }) + return false + }) + return groups +} + +// GetUserAllGroupsMembers returns all the UserGroupMembersEntry +func (k Keeper) GetUserAllGroupsMembers(ctx sdk.Context) []types.UserGroupMembersEntry { + var entries []types.UserGroupMembersEntry + k.IterateSubspaces(ctx, func(index int64, subspace types.Subspace) (stop bool) { + k.IterateSubspaceGroups(ctx, subspace.ID, func(index int64, group types.UserGroup) (stop bool) { + var members []string + k.IterateGroupMembers(ctx, subspace.ID, group.ID, func(index int64, member sdk.AccAddress) (stop bool) { + members = append(members, member.String()) + return false + }) + entries = append(entries, types.NewUserGroupMembersEntry(subspace.ID, group.ID, members)) + return false + }) + return false + }) + return entries +} + +// -------------------------------------------------------------------------------------------------------------------- + +// InitGenesis initializes the chain state based on the given GenesisState +func (k Keeper) InitGenesis(ctx sdk.Context, data types.GenesisState) { + // Initialize the subspaces + for _, subspaceData := range data.Subspaces { + k.SaveSubspace(ctx, subspaceData.Subspace) + k.SetGroupID(ctx, subspaceData.Subspace.ID, subspaceData.InitialGroupID) + } + + // Initialize the subspace id setting it to be the max id found + 1 + k.SetSubspaceID(ctx, data.InitialSubspaceID) + + // Initialize the groups with default permission PermissionNothing + // The real permission will be set later when initializing the various permissions + for _, group := range data.UserGroups { + k.SaveUserGroup(ctx, group) + } + + // Initialize the group members + for _, entry := range data.UserGroupsMembers { + // Initialize the members + for _, member := range entry.Members { + userAddr, err := sdk.AccAddressFromBech32(member) + if err != nil { + panic(err) + } + + err = k.AddUserToGroup(ctx, entry.SubspaceID, entry.GroupID, userAddr) + if err != nil { + panic(err) + } + } + } + + // Initialize the permissions + for _, entry := range data.ACL { + userAddr, err := sdk.AccAddressFromBech32(entry.User) + if err != nil { + panic(fmt.Errorf("invalid user address: %s", entry.User)) + } + k.SetUserPermissions(ctx, entry.SubspaceID, userAddr, entry.Permissions) + } +} diff --git a/x/subspaces/keeper/genesis_test.go b/x/subspaces/keeper/genesis_test.go new file mode 100644 index 0000000000..a732f8fe8d --- /dev/null +++ b/x/subspaces/keeper/genesis_test.go @@ -0,0 +1,403 @@ +package keeper_test + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +func (suite *KeeperTestsuite) TestKeeper_ExportGenesis() { + testCases := []struct { + name string + store func(ctx sdk.Context) + expGenesis *types.GenesisState + }{ + { + name: "subspace id is exported properly", + store: func(ctx sdk.Context) { + suite.k.SetSubspaceID(ctx, 1) + }, + expGenesis: types.NewGenesisState(1, nil, nil, nil, nil), + }, + { + name: "subspaces are exported correctly", + store: func(ctx sdk.Context) { + suite.k.SetSubspaceID(ctx, 3) + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveSubspace(ctx, types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + )) + }, + expGenesis: types.NewGenesisState( + 3, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + types.NewGenesisSubspace( + types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + nil, + nil, + ), + }, + { + name: "permissions are exported correctly", + store: func(ctx sdk.Context) { + suite.k.SetSubspaceID(ctx, 3) + suite.k.SaveSubspace(ctx, types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 2, sdkAddr, types.PermissionSetPermissions) + }, + expGenesis: types.NewGenesisState( + 3, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + []types.ACLEntry{ + types.NewACLEntry(2, "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", types.PermissionSetPermissions), + }, + nil, + nil, + ), + }, + { + name: "user groups are exported properly", + store: func(ctx sdk.Context) { + suite.k.SetSubspaceID(ctx, 3) + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SetGroupID(ctx, 1, 2) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + + suite.k.SaveSubspace(ctx, types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + )) + suite.k.SetGroupID(ctx, 2, 2) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 2, + 1, + "Another test group", + "This is another test group", + types.PermissionWrite, + )) + + userAddr, err = sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + err = suite.k.AddUserToGroup(ctx, 2, 1, userAddr) + + userAddr, err = sdk.AccAddressFromBech32("cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5") + suite.Require().NoError(err) + err = suite.k.AddUserToGroup(ctx, 2, 1, userAddr) + }, + expGenesis: types.NewGenesisState( + 3, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 2, + ), + types.NewGenesisSubspace( + types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + ), + 2, + ), + }, + nil, + []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + types.NewUserGroup( + 2, + 1, + "Another test group", + "This is another test group", + types.PermissionWrite, + ), + }, + []types.UserGroupMembersEntry{ + types.NewUserGroupMembersEntry(1, 1, []string{ + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + }), + types.NewUserGroupMembersEntry(2, 1, []string{ + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + }), + }, + ), + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + genesis := suite.k.ExportGenesis(ctx) + suite.Require().Equal(tc.expGenesis, genesis) + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_InitGenesis() { + testCases := []struct { + name string + genesis types.GenesisState + check func(ctx sdk.Context) + }{ + { + name: "all data is imported properly", + genesis: types.GenesisState{ + InitialSubspaceID: 3, + Subspaces: []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 2, + ), + types.NewGenesisSubspace( + types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + ), + 14, + ), + }, + ACL: []types.ACLEntry{ + types.NewACLEntry(2, "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", types.PermissionSetPermissions), + }, + UserGroups: []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + types.NewUserGroup( + 2, + 1, + "Another test group", + "This is another test group", + types.PermissionWrite, + ), + types.NewUserGroup( + 2, + 13, + "High id test group", + "This is another test group", + types.PermissionWrite, + ), + }, + UserGroupsMembers: []types.UserGroupMembersEntry{ + types.NewUserGroupMembersEntry(1, 1, []string{ + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + }), + types.NewUserGroupMembersEntry(2, 1, []string{ + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + }), + }, + }, + check: func(ctx sdk.Context) { + subspaceID, err := suite.k.GetSubspaceID(ctx) + suite.Require().NoError(err) + suite.Require().Equal(uint64(3), subspaceID) + + subspaces := suite.k.GetAllSubspaces(ctx) + suite.Require().Len(subspaces, 2) + + // Check the fist subspace data + firstSubspaceGroupID, err := suite.k.GetGroupID(ctx, 1) + suite.Require().NoError(err) + suite.Require().Equal(uint32(2), firstSubspaceGroupID) + + expectedFirstSubspaceGroups := []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + } + storedFirstSubspacesGroups := suite.k.GetSubspaceGroups(ctx, 1) + suite.Require().Equal(expectedFirstSubspaceGroups, storedFirstSubspacesGroups) + + var groupMembers = 0 + suite.k.IterateGroupMembers(ctx, 1, 1, func(index int64, member sdk.AccAddress) (stop bool) { + groupMembers += 1 + return false + }) + suite.Require().Equal(1, groupMembers) + + // Check the second subspace data + secondSubspaceGroupID, err := suite.k.GetGroupID(ctx, 2) + suite.Require().NoError(err) + suite.Require().Equal(uint32(14), secondSubspaceGroupID) + + expectedSecondSubspaceGroups := []types.UserGroup{ + types.NewUserGroup( + 2, + 1, + "Another test group", + "This is another test group", + types.PermissionWrite, + ), + types.NewUserGroup( + 2, + 13, + "High id test group", + "This is another test group", + types.PermissionWrite, + ), + } + storedSecondSubspaceGroups := suite.k.GetSubspaceGroups(ctx, 2) + suite.Require().Equal(expectedSecondSubspaceGroups, storedSecondSubspaceGroups) + + var anotherGroupMembers = 0 + suite.k.IterateGroupMembers(ctx, 2, 1, func(index int64, member sdk.AccAddress) (stop bool) { + anotherGroupMembers += 1 + return false + }) + suite.Require().Equal(2, anotherGroupMembers) + + // Check user permissions + userAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + + storedUserPermissions := suite.k.GetUserPermissions(ctx, 2, userAddr) + suite.Require().Equal(types.PermissionSetPermissions, storedUserPermissions) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + + suite.k.InitGenesis(ctx, tc.genesis) + + if tc.check != nil { + tc.check(ctx) + } + + }) + } +} diff --git a/x/subspaces/keeper/groups.go b/x/subspaces/keeper/groups.go new file mode 100644 index 0000000000..6104626cf8 --- /dev/null +++ b/x/subspaces/keeper/groups.go @@ -0,0 +1,112 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// SetGroupID sets the new group id for the specific subspace to the store +func (k Keeper) SetGroupID(ctx sdk.Context, subspaceID uint64, groupID uint32) { + store := ctx.KVStore(k.storeKey) + store.Set(types.GroupIDStoreKey(subspaceID), types.GetGroupIDBytes(groupID)) +} + +// GetGroupID gets the highest group id for the subspace with the given id +func (k Keeper) GetGroupID(ctx sdk.Context, subspaceID uint64) (groupID uint32, err error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.GroupIDStoreKey(subspaceID)) + if bz == nil { + return 0, sdkerrors.Wrap(types.ErrInvalidGenesis, "initial group ID hasn't been set") + } + + groupID = types.GetGroupIDFromBytes(bz) + return groupID, nil +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SaveUserGroup saves within the subspace having the given id the provided group +func (k Keeper) SaveUserGroup(ctx sdk.Context, group types.UserGroup) { + store := ctx.KVStore(k.storeKey) + + // Save the group + store.Set(types.GroupStoreKey(group.SubspaceID, group.ID), k.cdc.MustMarshal(&group)) + + k.Logger(ctx).Info("group saved", "subspace_id", group.SubspaceID, "group_id", group.ID) + k.AfterSubspaceGroupSaved(ctx, group.SubspaceID, group.ID) +} + +// HasUserGroup returns whether the given subspace has a group with the specified id or not +func (k Keeper) HasUserGroup(ctx sdk.Context, subspaceID uint64, groupID uint32) bool { + store := ctx.KVStore(k.storeKey) + return store.Has(types.GroupStoreKey(subspaceID, groupID)) +} + +// GetUserGroup returns the group associated with the given id inside the subspace with the provided id. +// If there is no group associated with the given id the function will return an empty group and false. +func (k Keeper) GetUserGroup(ctx sdk.Context, subspaceID uint64, groupID uint32) (group types.UserGroup, found bool) { + store := ctx.KVStore(k.storeKey) + key := types.GroupStoreKey(subspaceID, groupID) + if !store.Has(key) { + return group, false + } + + k.cdc.MustUnmarshal(store.Get(key), &group) + return group, true +} + +// DeleteUserGroup deletes the group with the given id from the subspace with the provided id +func (k Keeper) DeleteUserGroup(ctx sdk.Context, subspaceID uint64, groupID uint32) { + store := ctx.KVStore(k.storeKey) + + // Remove all the members from this group + var members []sdk.AccAddress + k.IterateGroupMembers(ctx, subspaceID, groupID, func(index int64, member sdk.AccAddress) (stop bool) { + members = append(members, member) + return false + }) + + for _, member := range members { + k.RemoveUserFromGroup(ctx, subspaceID, groupID, member) + } + + // Delete the group + store.Delete(types.GroupStoreKey(subspaceID, groupID)) + + k.Logger(ctx).Info("group deleted", "subspace_id", subspaceID, "group_id", groupID) + k.AfterSubspaceGroupDeleted(ctx, subspaceID, groupID) +} + +// -------------------------------------------------------------------------------------------------------------------- + +// AddUserToGroup adds the given user to the group having the provided id inside the specified subspace. +// If the group does not exist inside the subspace, it returns an error. +func (k Keeper) AddUserToGroup(ctx sdk.Context, subspaceID uint64, groupID uint32, user sdk.AccAddress) error { + if !k.HasUserGroup(ctx, subspaceID, groupID) { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group with id %d does not exist", groupID) + } + + store := ctx.KVStore(k.storeKey) + store.Set(types.GroupMemberStoreKey(subspaceID, groupID, user), []byte{0x01}) + + k.AfterSubspaceGroupMemberAdded(ctx, subspaceID, groupID, user) + + return nil +} + +// IsMemberOfGroup returns whether the given user is part of the group with +// the specified id inside the provided subspace +func (k Keeper) IsMemberOfGroup(ctx sdk.Context, subspaceID uint64, groupID uint32, user sdk.AccAddress) bool { + store := ctx.KVStore(k.storeKey) + return store.Has(types.GroupMemberStoreKey(subspaceID, groupID, user)) +} + +// RemoveUserFromGroup removes the specified user from the subspace group having the given id. +func (k Keeper) RemoveUserFromGroup(ctx sdk.Context, subspaceID uint64, groupID uint32, user sdk.AccAddress) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.GroupMemberStoreKey(subspaceID, groupID, user)) + + k.AfterSubspaceGroupMemberRemoved(ctx, subspaceID, groupID, user) +} diff --git a/x/subspaces/keeper/groups_test.go b/x/subspaces/keeper/groups_test.go new file mode 100644 index 0000000000..3dfa989e72 --- /dev/null +++ b/x/subspaces/keeper/groups_test.go @@ -0,0 +1,541 @@ +package keeper_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +func (suite *KeeperTestsuite) TestKeeper_SetGroupID() { + testCases := []struct { + name string + subspaceID uint64 + groupID uint32 + check func(ctx sdk.Context) + }{ + { + name: "zero group id", + subspaceID: 1, + groupID: 0, + check: func(ctx sdk.Context) { + store := ctx.KVStore(suite.storeKey) + groupID := types.GetGroupIDFromBytes(store.Get(types.GroupIDStoreKey(1))) + suite.Require().Equal(uint32(0), groupID) + }, + }, + { + name: "non-zero group id", + subspaceID: 1, + groupID: 5, + check: func(ctx sdk.Context) { + store := ctx.KVStore(suite.storeKey) + groupID := types.GetGroupIDFromBytes(store.Get(types.GroupIDStoreKey(1))) + suite.Require().Equal(uint32(5), groupID) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + + suite.k.SetGroupID(ctx, tc.subspaceID, tc.groupID) + if tc.check != nil { + tc.check(ctx) + } + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_GetGroupID() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + shouldErr bool + expID uint32 + }{ + { + name: "group id not set", + subspaceID: 1, + shouldErr: true, + }, + { + name: "group id set", + store: func(ctx sdk.Context) { + store := ctx.KVStore(suite.storeKey) + store.Set(types.GroupIDStoreKey(1), types.GetGroupIDBytes(1)) + }, + subspaceID: 1, + shouldErr: false, + expID: 1, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + id, err := suite.k.GetGroupID(ctx, tc.subspaceID) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expID, id) + } + }) + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +func (suite *KeeperTestsuite) TestKeeper_SaveUserGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + group types.UserGroup + permissions types.Permission + check func(ctx sdk.Context) + }{ + { + name: "non existing group is stored properly", + group: types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + permissions: types.PermissionWrite, + check: func(ctx sdk.Context) { + group, found := suite.k.GetUserGroup(ctx, 1, 1) + suite.Require().True(found) + suite.Require().Equal(types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), group) + }, + }, + { + name: "existing group is updated properly", + store: func(ctx sdk.Context) { + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + group: types.NewUserGroup( + 1, + 1, + "Edited test group", + "This is an edited test group", + types.PermissionChangeInfo, + ), + permissions: types.PermissionManageGroups, + check: func(ctx sdk.Context) { + group, found := suite.k.GetUserGroup(ctx, 1, 1) + suite.Require().True(found) + suite.Require().Equal(types.NewUserGroup( + 1, + 1, + "Edited test group", + "This is an edited test group", + types.PermissionChangeInfo, + ), group) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + suite.k.SaveUserGroup(ctx, tc.group) + if tc.check != nil { + tc.check(ctx) + } + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_HasUserGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + groupID uint32 + expResult bool + }{ + { + name: "not found group returns false", + subspaceID: 1, + groupID: 1, + expResult: false, + }, + { + name: "found group returns true", + store: func(ctx sdk.Context) { + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + subspaceID: 1, + groupID: 1, + expResult: true, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + result := suite.k.HasUserGroup(ctx, tc.subspaceID, tc.groupID) + suite.Require().Equal(tc.expResult, result) + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_GetUserGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + groupID uint32 + expFound bool + expGroup types.UserGroup + }{ + { + name: "not found group returns false", + subspaceID: 1, + groupID: 1, + expFound: false, + }, + { + name: "found group returns true", + store: func(ctx sdk.Context) { + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + subspaceID: 1, + groupID: 1, + expFound: true, + expGroup: types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + group, found := suite.k.GetUserGroup(ctx, tc.subspaceID, tc.groupID) + suite.Require().Equal(tc.expFound, found) + if tc.expFound { + suite.Require().Equal(tc.expGroup, group) + } + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_DeleteUserGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + groupID uint32 + check func(ctx sdk.Context) + }{ + { + name: "non existing group is deleted properly", + subspaceID: 1, + groupID: 1, + check: func(ctx sdk.Context) { + hasGroup := suite.k.HasUserGroup(ctx, 1, 1) + suite.Require().False(hasGroup) + }, + }, + { + name: "existing group is deleted properly and members are cleared", + store: func(ctx sdk.Context) { + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + + userAddr, err = sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + }, + subspaceID: 1, + groupID: 1, + check: func(ctx sdk.Context) { + hasGroup := suite.k.HasUserGroup(ctx, 1, 1) + suite.Require().False(hasGroup) + + var members []sdk.AccAddress + suite.k.IterateGroupMembers(ctx, 1, 1, func(index int64, member sdk.AccAddress) (stop bool) { + members = append(members, member) + return false + }) + suite.Require().Empty(members) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + suite.k.DeleteUserGroup(ctx, tc.subspaceID, tc.groupID) + if tc.check != nil { + tc.check(ctx) + } + }) + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +func (suite *KeeperTestsuite) TestKeeper_AddUserToGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + groupID uint32 + user string + shouldErr bool + check func(ctx sdk.Context) + }{ + { + name: "non existing group returns error", + subspaceID: 1, + groupID: 1, + user: "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + shouldErr: true, + }, + { + name: "user is added properly to group", + store: func(ctx sdk.Context) { + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + subspaceID: 1, + groupID: 1, + user: "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + shouldErr: false, + check: func(ctx sdk.Context) { + userAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + + isMember := suite.k.IsMemberOfGroup(ctx, 1, 1, userAddr) + suite.Require().True(isMember) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + userAddr, err := sdk.AccAddressFromBech32(tc.user) + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, tc.subspaceID, tc.groupID, userAddr) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_IsMemberOfGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + groupID uint32 + user string + expResult bool + }{ + { + name: "not being part of group returns false", + subspaceID: 1, + groupID: 1, + user: "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + expResult: false, + }, + { + name: "being part of group returns true", + store: func(ctx sdk.Context) { + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + }, + subspaceID: 1, + groupID: 1, + user: "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + expResult: true, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + userAddr, err := sdk.AccAddressFromBech32(tc.user) + suite.Require().NoError(err) + + result := suite.k.IsMemberOfGroup(ctx, tc.subspaceID, tc.groupID, userAddr) + suite.Require().Equal(tc.expResult, result) + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_RemoveUserFromGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + groupID uint32 + user string + check func(ctx sdk.Context) + }{ + { + name: "non existing user is removed properly", + subspaceID: 1, + groupID: 1, + user: "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + check: func(ctx sdk.Context) { + userAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + + isMember := suite.k.IsMemberOfGroup(ctx, 1, 1, userAddr) + suite.Require().False(isMember) + }, + }, + { + name: "existing user is removed properly", + store: func(ctx sdk.Context) { + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + }, + subspaceID: 1, + groupID: 1, + user: "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + check: func(ctx sdk.Context) { + userAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + + isMember := suite.k.IsMemberOfGroup(ctx, 1, 1, userAddr) + suite.Require().False(isMember) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + userAddr, err := sdk.AccAddressFromBech32(tc.user) + suite.Require().NoError(err) + + suite.k.RemoveUserFromGroup(ctx, tc.subspaceID, tc.groupID, userAddr) + if tc.check != nil { + tc.check(ctx) + } + }) + } +} diff --git a/x/subspaces/keeper/grpc_query.go b/x/subspaces/keeper/grpc_query.go new file mode 100644 index 0000000000..dc3397efd0 --- /dev/null +++ b/x/subspaces/keeper/grpc_query.go @@ -0,0 +1,174 @@ +package keeper + +import ( + "bytes" + "context" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var _ types.QueryServer = Keeper{} + +// Subspaces implements the Query/Subspaces gRPC method +func (k Keeper) Subspaces(ctx context.Context, request *types.QuerySubspacesRequest) (*types.QuerySubspacesResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + store := sdkCtx.KVStore(k.storeKey) + subspacesStore := prefix.NewStore(store, types.SubspacePrefix) + + var subspaces []types.Subspace + pageRes, err := query.Paginate(subspacesStore, request.Pagination, func(key []byte, value []byte) error { + var subspace types.Subspace + if err := k.cdc.Unmarshal(value, &subspace); err != nil { + return status.Error(codes.Internal, err.Error()) + } + + subspaces = append(subspaces, subspace) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QuerySubspacesResponse{Subspaces: subspaces, Pagination: pageRes}, nil +} + +// Subspace implements the Query/Subspace gRPC method +func (k Keeper) Subspace(ctx context.Context, request *types.QuerySubspaceRequest) (*types.QuerySubspaceResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + subspace, found := k.GetSubspace(sdkCtx, request.SubspaceId) + if !found { + return nil, sdkerrors.Wrapf(sdkerrors.ErrNotFound, "subspace with id %d not found", request.SubspaceId) + } + + return &types.QuerySubspaceResponse{Subspace: subspace}, nil +} + +// UserGroups implements the Query/UserGroups gRPC method +func (k Keeper) UserGroups(ctx context.Context, request *types.QueryUserGroupsRequest) (*types.QueryUserGroupsResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + // Check if the subspace exists + if !k.HasSubspace(sdkCtx, request.SubspaceId) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", request.SubspaceId) + } + + store := sdkCtx.KVStore(k.storeKey) + storePrefix := types.GroupsStoreKey(request.SubspaceId) + groupsStore := prefix.NewStore(store, storePrefix) + + var groups []types.UserGroup + pageRes, err := query.Paginate(groupsStore, request.Pagination, func(key []byte, value []byte) error { + var group types.UserGroup + err := k.cdc.Unmarshal(value, &group) + if err != nil { + return err + } + + groups = append(groups, group) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryUserGroupsResponse{Groups: groups, Pagination: pageRes}, nil +} + +// UserGroup implements the Query/UserGroup gRPC method +func (k Keeper) UserGroup(ctx context.Context, request *types.QueryUserGroupRequest) (*types.QueryUserGroupResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + // Check if the subspace exists + if !k.HasSubspace(sdkCtx, request.SubspaceId) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", request.SubspaceId) + } + + // Get the group + group, found := k.GetUserGroup(sdkCtx, request.SubspaceId, request.GroupId) + if !found { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group %d could not be found", request.GroupId) + } + + return &types.QueryUserGroupResponse{Group: group}, nil +} + +// UserGroupMembers implements the Query/UserGroupMembers gRPC method +func (k Keeper) UserGroupMembers(ctx context.Context, request *types.QueryUserGroupMembersRequest) (*types.QueryUserGroupMembersResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + // Check if the subspace exists + if !k.HasSubspace(sdkCtx, request.SubspaceId) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", request.SubspaceId) + } + + // Check if the group exists + if !k.HasUserGroup(sdkCtx, request.SubspaceId, request.GroupId) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group %d could not be found", request.GroupId) + } + + store := sdkCtx.KVStore(k.storeKey) + storePrefix := types.GroupMembersStoreKey(request.SubspaceId, request.GroupId) + membersStore := prefix.NewStore(store, storePrefix) + + var members []string + pageRes, err := query.Paginate(membersStore, request.Pagination, func(key []byte, value []byte) error { + member := types.GetAddressFromBytes(bytes.TrimPrefix(key, storePrefix)) + members = append(members, member.String()) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryUserGroupMembersResponse{Members: members, Pagination: pageRes}, nil +} + +// UserPermissions implements the Query/UserPermissions gRPC method +func (k Keeper) UserPermissions(ctx context.Context, request *types.QueryUserPermissionsRequest) (*types.QueryUserPermissionsResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + // Check if the subspace exists + if !k.HasSubspace(sdkCtx, request.SubspaceId) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", request.SubspaceId) + } + + sdkAddr, err := sdk.AccAddressFromBech32(request.User) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid user address: %s", request.User) + } + + // Get the user specific permissions + userPermission := k.GetUserPermissions(sdkCtx, request.SubspaceId, sdkAddr) + groupPermissions := k.GetGroupsInheritedPermissions(sdkCtx, request.SubspaceId, sdkAddr) + permissionResult := types.CombinePermissions(userPermission, groupPermissions) + + // Get the details of all the permissions + var details []types.PermissionDetail + if userPermission != types.PermissionNothing { + details = append(details, types.NewPermissionDetailUser(request.User, userPermission)) + } + + k.IterateSubspaceGroups(sdkCtx, request.SubspaceId, func(index int64, group types.UserGroup) (stop bool) { + if k.IsMemberOfGroup(sdkCtx, request.SubspaceId, group.ID, sdkAddr) { + details = append(details, types.NewPermissionDetailGroup(group.ID, group.Permissions)) + } + return false + }) + + return &types.QueryUserPermissionsResponse{ + Permissions: permissionResult, + Details: details, + }, nil +} diff --git a/x/subspaces/keeper/grpc_query_test.go b/x/subspaces/keeper/grpc_query_test.go new file mode 100644 index 0000000000..c75a35bafb --- /dev/null +++ b/x/subspaces/keeper/grpc_query_test.go @@ -0,0 +1,510 @@ +package keeper_test + +import ( + "time" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" +) + +func (suite *KeeperTestsuite) TestQueryServer_Subspaces() { + testCases := []struct { + name string + store func(ctx sdk.Context) + req *types.QuerySubspacesRequest + expSubspaces []types.Subspace + }{ + + { + name: "invalid pagination returns empty slice", + req: types.NewQuerySubspacesRequest(&query.PageRequest{ + Limit: 1, + Offset: 1, + }), + expSubspaces: nil, + }, + { + name: "valid pagination returns result properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveSubspace(ctx, types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + req: &types.QuerySubspacesRequest{ + Pagination: &query.PageRequest{ + Offset: 1, + Limit: 1, + CountTotal: true, + }, + }, + expSubspaces: []types.Subspace{ + types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + res, err := suite.k.Subspaces(sdk.WrapSDKContext(ctx), tc.req) + suite.Require().NoError(err) + suite.Require().Equal(tc.expSubspaces, res.Subspaces) + }) + } +} + +func (suite *KeeperTestsuite) TestQueryServer_Subspace() { + testCases := []struct { + name string + store func(ctx sdk.Context) + request *types.QuerySubspaceRequest + shouldErr bool + expResponse *types.QuerySubspaceResponse + }{ + { + name: "not found subspace returns error", + request: types.NewQuerySubspaceRequest(1), + shouldErr: true, + }, + { + name: "found subspace is returned properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + request: types.NewQuerySubspaceRequest(1), + shouldErr: false, + expResponse: &types.QuerySubspaceResponse{ + Subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + response, err := suite.k.Subspace(sdk.WrapSDKContext(ctx), tc.request) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expResponse, response) + } + }) + } +} + +func (suite *KeeperTestsuite) TestQueryServer_UserGroups() { + testCases := []struct { + name string + store func(ctx sdk.Context) + req *types.QueryUserGroupsRequest + shouldErr bool + expGroups []types.UserGroup + }{ + { + name: "non existing subspace returns error", + req: types.NewQueryUserGroupsRequest(1, nil), + shouldErr: true, + }, + { + name: "existing groups are returned properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "First test group", + "This is a test group", + types.PermissionWrite, + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 2, + "Second test group", + "This is a test group", + types.PermissionWrite, + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 3, + "Third test group", + "This is a test group", + types.PermissionWrite, + )) + }, + req: types.NewQueryUserGroupsRequest(1, &query.PageRequest{ + Offset: 1, + Limit: 2, + }), + shouldErr: false, + expGroups: []types.UserGroup{ + types.NewUserGroup( + 1, + 2, + "Second test group", + "This is a test group", + types.PermissionWrite, + ), + types.NewUserGroup( + 1, + 3, + "Third test group", + "This is a test group", + types.PermissionWrite, + ), + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + res, err := suite.k.UserGroups(sdk.WrapSDKContext(ctx), tc.req) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expGroups, res.Groups) + } + }) + } +} + +func (suite *KeeperTestsuite) TestQueryServer_UserGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + req *types.QueryUserGroupRequest + shouldErr bool + expGroup types.UserGroup + }{ + { + name: "not found group returns error", + req: types.NewQueryUserGroupRequest(1, 1), + shouldErr: true, + }, + { + name: "found group is returned properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + req: types.NewQueryUserGroupRequest(1, 1), + shouldErr: false, + expGroup: types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + res, err := suite.k.UserGroup(sdk.WrapSDKContext(ctx), tc.req) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expGroup, res.Group) + } + }) + } +} + +func (suite *KeeperTestsuite) TestQueryServer_UserGroupMembers() { + testCases := []struct { + name string + store func(ctx sdk.Context) + req *types.QueryUserGroupMembersRequest + shouldErr bool + expMembers []string + }{ + { + name: "non existing subspace returns error", + req: types.NewQueryUserGroupMembersRequest(1, 1, nil), + shouldErr: true, + }, + { + name: "non existing group returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + req: types.NewQueryUserGroupMembersRequest(1, 1, nil), + shouldErr: true, + }, + { + name: "existing group members are returned properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + + userAddr, err = sdk.AccAddressFromBech32("cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + + userAddr, err = sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + }, + req: types.NewQueryUserGroupMembersRequest(1, 1, &query.PageRequest{ + Offset: 1, + Limit: 1, + }), + shouldErr: false, + expMembers: []string{"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5"}, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + res, err := suite.k.UserGroupMembers(sdk.WrapSDKContext(ctx), tc.req) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expMembers, res.Members) + } + }) + } +} + +func (suite *KeeperTestsuite) TestQueryServer_UserPermissions() { + testCases := []struct { + name string + store func(ctx sdk.Context) + req *types.QueryUserPermissionsRequest + shouldErr bool + expResponse types.QueryUserPermissionsResponse + }{ + { + name: "not found subspace returns error", + shouldErr: true, + req: types.NewQueryUserPermissionsRequest( + 1, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + }, + { + name: "not found user returns PermissionNothing", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + req: types.NewQueryUserPermissionsRequest( + 1, + "cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e", + ), + shouldErr: false, + expResponse: types.QueryUserPermissionsResponse{ + Permissions: types.PermissionNothing, + Details: nil, + }, + }, + { + name: "existing permissions are returned correctly", + store: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e") + suite.Require().NoError(err) + + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionChangeInfo, + )) + err = suite.k.AddUserToGroup(ctx, 1, 1, sdkAddr) + suite.Require().NoError(err) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 2, + "Another test group", + "This is another test group", + types.PermissionSetPermissions, + )) + err = suite.k.AddUserToGroup(ctx, 1, 2, sdkAddr) + suite.Require().NoError(err) + + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionWrite) + }, + req: types.NewQueryUserPermissionsRequest( + 1, + "cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e", + ), + shouldErr: false, + expResponse: types.QueryUserPermissionsResponse{ + Permissions: types.PermissionWrite | types.PermissionChangeInfo | types.PermissionSetPermissions, + Details: []types.PermissionDetail{ + types.NewPermissionDetailUser("cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e", types.PermissionWrite), + types.NewPermissionDetailGroup(1, types.PermissionChangeInfo), + types.NewPermissionDetailGroup(2, types.PermissionSetPermissions), + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + res, err := suite.k.UserPermissions(sdk.WrapSDKContext(ctx), tc.req) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expResponse.Permissions, res.Permissions) + suite.Require().Equal(tc.expResponse.Details, res.Details) + } + }) + } +} diff --git a/x/subspaces/keeper/hooks.go b/x/subspaces/keeper/hooks.go new file mode 100644 index 0000000000..5a6035d03e --- /dev/null +++ b/x/subspaces/keeper/hooks.go @@ -0,0 +1,68 @@ +package keeper + +// DONTCOVER + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// Implements SubspacesHooks interface +var _ types.SubspacesHooks = Keeper{} + +// AfterSubspaceSaved - call if hook is registered +func (k Keeper) AfterSubspaceSaved(ctx sdk.Context, subspaceID uint64) { + if k.hooks != nil { + k.hooks.AfterSubspaceSaved(ctx, subspaceID) + } +} + +// AfterSubspaceDeleted - call if hook is registered +func (k Keeper) AfterSubspaceDeleted(ctx sdk.Context, subspaceID uint64) { + if k.hooks != nil { + k.hooks.AfterSubspaceDeleted(ctx, subspaceID) + } +} + +// AfterSubspaceGroupSaved - call if hook is registered +func (k Keeper) AfterSubspaceGroupSaved(ctx sdk.Context, subspaceID uint64, groupID uint32) { + if k.hooks != nil { + k.hooks.AfterSubspaceGroupSaved(ctx, subspaceID, groupID) + } +} + +// AfterSubspaceGroupMemberAdded - call if hook is registered +func (k Keeper) AfterSubspaceGroupMemberAdded(ctx sdk.Context, subspaceID uint64, groupID uint32, user sdk.AccAddress) { + if k.hooks != nil { + k.hooks.AfterSubspaceGroupMemberAdded(ctx, subspaceID, groupID, user) + } +} + +// AfterSubspaceGroupMemberRemoved - call if hook is registered +func (k Keeper) AfterSubspaceGroupMemberRemoved(ctx sdk.Context, subspaceID uint64, groupID uint32, user sdk.AccAddress) { + if k.hooks != nil { + k.hooks.AfterSubspaceGroupMemberRemoved(ctx, subspaceID, groupID, user) + } +} + +// AfterSubspaceGroupDeleted - call if hook is registered +func (k Keeper) AfterSubspaceGroupDeleted(ctx sdk.Context, subspaceID uint64, groupID uint32) { + if k.hooks != nil { + k.hooks.AfterSubspaceGroupDeleted(ctx, subspaceID, groupID) + } +} + +// AfterUserPermissionSet - call if hook is registered +func (k Keeper) AfterUserPermissionSet(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress, permissions types.Permission) { + if k.hooks != nil { + k.hooks.AfterUserPermissionSet(ctx, subspaceID, user, permissions) + } +} + +// AfterUserPermissionRemoved - call if hook is registered +func (k Keeper) AfterUserPermissionRemoved(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress) { + if k.hooks != nil { + k.hooks.AfterUserPermissionRemoved(ctx, subspaceID, user) + } +} diff --git a/x/subspaces/keeper/invariants.go b/x/subspaces/keeper/invariants.go new file mode 100644 index 0000000000..fdbfe76205 --- /dev/null +++ b/x/subspaces/keeper/invariants.go @@ -0,0 +1,97 @@ +package keeper + +import ( + "fmt" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// RegisterInvariants registers all subspaces invariants +func RegisterInvariants(ir sdk.InvariantRegistry, keeper Keeper) { + ir.RegisterRoute(types.ModuleName, "valid-subspaces", + ValidSubspacesInvariant(keeper)) + ir.RegisterRoute(types.ModuleName, "valid-user-groups", + ValidUserGroupsInvariant(keeper)) +} + +// AllInvariants runs all invariants of the module +func AllInvariants(k Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + res, broken := ValidSubspacesInvariant(k)(ctx) + if broken { + return res, true + } + + res, broken = ValidUserGroupsInvariant(k)(ctx) + if broken { + return res, true + } + + return "Every invariant condition is fulfilled correctly", false + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +// ValidSubspacesInvariant checks that all the subspaces are valid +func ValidSubspacesInvariant(k Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + var invalidSubspaces []types.Subspace + k.IterateSubspaces(ctx, func(_ int64, subspace types.Subspace) (stop bool) { + err := subspace.Validate() + if err != nil { + invalidSubspaces = append(invalidSubspaces, subspace) + } + return false + }) + + return sdk.FormatInvariant(types.ModuleName, "invalid subspaces", + fmt.Sprintf("the following subspaces are invalid:\n %s", formatOutputSubspaces(invalidSubspaces)), + ), invalidSubspaces != nil + } +} + +// formatOutputSubspaces concatenate the subspaces given into a unique string +func formatOutputSubspaces(subspaces []types.Subspace) (outputSubspaces string) { + for _, subspace := range subspaces { + outputSubspaces += fmt.Sprintf("%d\n", subspace.ID) + } + return outputSubspaces +} + +// -------------------------------------------------------------------------------------------------------------------- + +// ValidUserGroupsInvariant checks that all the subspaces are valid +func ValidUserGroupsInvariant(k Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + var invalidUserGroups []types.UserGroup + k.IterateUserGroups(ctx, func(_ int64, group types.UserGroup) (stop bool) { + err := group.Validate() + if err != nil { + // The group is not valid + invalidUserGroups = append(invalidUserGroups, group) + } + + if !k.HasSubspace(ctx, group.SubspaceID) { + // The subspace for this group does not exist anymore + invalidUserGroups = append(invalidUserGroups, group) + } + + return false + }) + + return sdk.FormatInvariant(types.ModuleName, "invalid user groups", + fmt.Sprintf("the following user groups are invalid:\n %s", formatOutputUserGroups(invalidUserGroups)), + ), invalidUserGroups != nil + } +} + +// formatOutputUserGroups concatenate the subspaces given into a unique string +func formatOutputUserGroups(groups []types.UserGroup) (outputUserGroups string) { + for _, group := range groups { + outputUserGroups += fmt.Sprintf("%d\n", group.ID) + } + return outputUserGroups +} diff --git a/x/subspaces/keeper/invariants_test.go b/x/subspaces/keeper/invariants_test.go new file mode 100644 index 0000000000..d284284c9e --- /dev/null +++ b/x/subspaces/keeper/invariants_test.go @@ -0,0 +1,98 @@ +package keeper_test + +import ( + "time" + + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (suite *KeeperTestsuite) TestInvariants() { + tests := []struct { + name string + store func(ctx sdk.Context) + expBroken bool + }{ + { + name: "valid subspace invariant violated", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + expBroken: true, + }, + { + name: "valid user groups invariant violated - invalid data", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 0, + "This is a test group", + "This is a test group", + types.PermissionWrite, + )) + }, + expBroken: true, + }, + { + name: "valid user groups invariant violated - missing associated subspace", + store: func(ctx sdk.Context) { + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "This is a test group", + "This is a test group", + types.PermissionWrite, + )) + }, + expBroken: true, + }, + { + name: "no invariant is violated", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + expBroken: false, + }, + } + + for _, test := range tests { + test := test + suite.Run(test.name, func() { + ctx, _ := suite.ctx.CacheContext() + if test.store != nil { + test.store(ctx) + } + + _, broken := keeper.AllInvariants(suite.k)(ctx) + suite.Require().Equal(test.expBroken, broken) + }) + } +} diff --git a/x/subspaces/keeper/keeper.go b/x/subspaces/keeper/keeper.go new file mode 100644 index 0000000000..728bd2e6ab --- /dev/null +++ b/x/subspaces/keeper/keeper.go @@ -0,0 +1,38 @@ +package keeper + +import ( + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/libs/log" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +type Keeper struct { + storeKey sdk.StoreKey + cdc codec.BinaryCodec + hooks types.SubspacesHooks +} + +// NewKeeper creates new instances of the subspaces keeper +func NewKeeper(cdc codec.BinaryCodec, storeKey sdk.StoreKey) Keeper { + return Keeper{ + storeKey: storeKey, + cdc: cdc, + } +} + +// Logger returns a module-specific logger +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", "x/"+types.ModuleName) +} + +// SetHooks allows to set the subspaces hooks +func (k Keeper) SetHooks(sh types.SubspacesHooks) Keeper { + if k.hooks != nil { + panic("cannot set subspaces hooks twice") + } + + k.hooks = sh + return k +} diff --git a/x/subspaces/keeper/keeper_test.go b/x/subspaces/keeper/keeper_test.go new file mode 100644 index 0000000000..521ca8312b --- /dev/null +++ b/x/subspaces/keeper/keeper_test.go @@ -0,0 +1,46 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +func TestKeeper_SetHooks(t *testing.T) { + testCases := []struct { + name string + setup func(k keeper.Keeper) keeper.Keeper + shouldErr bool + }{ + { + name: "setting already set hooks returns error", + setup: func(k keeper.Keeper) keeper.Keeper { + return k.SetHooks(types.MultiSubspacesHooks{}) + }, + shouldErr: true, + }, + { + name: "setting hooks not set works properly", + shouldErr: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + k := keeper.NewKeeper(nil, nil) + if tc.setup != nil { + k = tc.setup(k) + } + + if tc.shouldErr { + require.Panics(t, func() { k.SetHooks(types.MultiSubspacesHooks{}) }) + } else { + require.NotPanics(t, func() { k.SetHooks(types.MultiSubspacesHooks{}) }) + } + }) + } +} diff --git a/x/subspaces/keeper/msg_server.go b/x/subspaces/keeper/msg_server.go new file mode 100644 index 0000000000..94591cf4c6 --- /dev/null +++ b/x/subspaces/keeper/msg_server.go @@ -0,0 +1,499 @@ +package keeper + +import ( + "context" + "fmt" + "time" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the stored MsgServer interface +// for the provided keeper +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{Keeper: keeper} +} + +var _ types.MsgServer = msgServer{} + +// CreateSubspace defines a rpc method for MsgCreateSubspace +func (k msgServer) CreateSubspace(goCtx context.Context, msg *types.MsgCreateSubspace) (*types.MsgCreateSubspaceResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Get the next subspace ID + subspaceID, err := k.GetSubspaceID(ctx) + if err != nil { + return nil, err + } + + // Create and validate the subspace + subspace := types.NewSubspace(subspaceID, msg.Name, msg.Description, msg.Owner, msg.Creator, msg.Treasury, ctx.BlockTime()) + if err := subspace.Validate(); err != nil { + return nil, err + } + + // Save the subspace + k.SaveSubspace(ctx, subspace) + + // Update the id for the next subspace + k.SetSubspaceID(ctx, subspace.ID+1) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, subspace.Creator), + ), + sdk.NewEvent( + types.EventTypeCreateSubspace, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", subspaceID)), + sdk.NewAttribute(types.AttributeKeySubspaceName, subspace.Name), + sdk.NewAttribute(types.AttributeKeySubspaceCreator, subspace.Creator), + sdk.NewAttribute(types.AttributeKeyCreationTime, subspace.CreationTime.Format(time.RFC3339)), + ), + }) + + return &types.MsgCreateSubspaceResponse{ + SubspaceID: subspace.ID, + }, nil +} + +// EditSubspace defines a rpc method for MsgEditSubspace +func (k msgServer) EditSubspace(goCtx context.Context, msg *types.MsgEditSubspace) (*types.MsgEditSubspaceResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check the if the subspace exists + subspace, exists := k.GetSubspace(ctx, msg.SubspaceID) + if !exists { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + signer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address: %s", msg.Signer) + } + + // Check the permission to edit + if !k.HasPermission(ctx, msg.SubspaceID, signer, types.PermissionChangeInfo) { + return nil, sdkerrors.Wrap(types.ErrPermissionDenied, "you cannot manage this subspace") + } + + // Update the subspace and validate it + updated := subspace.Update(types.NewSubspaceUpdate(msg.Name, msg.Description, msg.Owner, msg.Treasury)) + err = updated.Validate() + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } + + // Save the subspace + k.SaveSubspace(ctx, updated) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer), + ), + sdk.NewEvent( + types.EventTypeEditSubspace, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", updated.ID)), + ), + }) + + return &types.MsgEditSubspaceResponse{}, nil +} + +// DeleteSubspace defines a rpc method for MsgDeleteSubspace +func (k msgServer) DeleteSubspace(goCtx context.Context, msg *types.MsgDeleteSubspace) (*types.MsgDeleteSubspaceResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check the if the subspace exists + if !k.HasSubspace(ctx, msg.SubspaceID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + signer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address: %s", msg.Signer) + } + + // Check the permission to edit + if !k.HasPermission(ctx, msg.SubspaceID, signer, types.PermissionDeleteSubspace) { + return nil, sdkerrors.Wrap(types.ErrPermissionDenied, "you cannot manage this subspace") + } + + // Delete the subspace + k.Keeper.DeleteSubspace(ctx, msg.SubspaceID) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer), + ), + sdk.NewEvent( + types.EventTypeDeleteSubspace, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + ), + }) + + return &types.MsgDeleteSubspaceResponse{}, nil +} + +// CreateUserGroup defines a rpc method for MsgCreateUserGroup +func (k msgServer) CreateUserGroup(goCtx context.Context, msg *types.MsgCreateUserGroup) (*types.MsgCreateUserGroupResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + if !k.HasSubspace(ctx, msg.SubspaceID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group with id %d not found", msg.SubspaceID) + } + + creator, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address: %s", msg.Creator) + } + + // Check the permission to create a group + if !k.HasPermission(ctx, msg.SubspaceID, creator, types.PermissionManageGroups) { + return nil, sdkerrors.Wrap(types.ErrPermissionDenied, "you cannot create user groups in this subspace") + } + + // Get the next group ID + groupID, err := k.GetGroupID(ctx, msg.SubspaceID) + if err != nil { + return nil, err + } + + // Create and validate the group + group := types.NewUserGroup(msg.SubspaceID, groupID, msg.Name, msg.Description, msg.DefaultPermissions) + if err := group.Validate(); err != nil { + return nil, err + } + + // Save the group + k.SaveUserGroup(ctx, group) + + // Update the id for the next group + k.SetGroupID(ctx, msg.SubspaceID, group.ID+1) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Creator), + ), + sdk.NewEvent( + types.EventTypeCreateUserGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeKeyUserGroupID, fmt.Sprintf("%d", group.ID)), + ), + }) + + return &types.MsgCreateUserGroupResponse{GroupID: groupID}, nil +} + +// EditUserGroup defines a rpc method for MsgEditUserGroup +func (k msgServer) EditUserGroup(goCtx context.Context, msg *types.MsgEditUserGroup) (*types.MsgEditUserGroupResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + if !k.HasSubspace(ctx, msg.SubspaceID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group with id %d not found", msg.SubspaceID) + } + + // Check if the group exists + group, found := k.GetUserGroup(ctx, msg.SubspaceID, msg.GroupID) + if !found { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group with id %d not found", msg.GroupID) + } + + signer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address: %s", msg.Signer) + } + + // Check the permission to create a group + if !k.HasPermission(ctx, msg.SubspaceID, signer, types.PermissionManageGroups) { + return nil, sdkerrors.Wrap(types.ErrPermissionDenied, "you cannot manage user groups in this subspace") + } + + // Update the group and validate it + updated := group.Update(types.NewGroupUpdate(msg.Name, msg.Description)) + err = updated.Validate() + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } + + // Save the updated group + k.SaveUserGroup(ctx, updated) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer), + ), + sdk.NewEvent( + types.EventTypeEditUserGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeKeyUserGroupID, fmt.Sprintf("%d", msg.GroupID)), + ), + }) + + return &types.MsgEditUserGroupResponse{}, nil +} + +// SetUserGroupPermissions defines a rpc method for MsgSetUserGroupPermissions +func (k msgServer) SetUserGroupPermissions(goCtx context.Context, msg *types.MsgSetUserGroupPermissions) (*types.MsgSetUserGroupPermissionsResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + if !k.HasSubspace(ctx, msg.SubspaceID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + // Check if the group exists + group, found := k.GetUserGroup(ctx, msg.SubspaceID, msg.GroupID) + if !found { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group with id %d not found", msg.GroupID) + } + + signer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address: %s", msg.Signer) + } + + // Check the permissions + if !k.HasPermission(ctx, msg.SubspaceID, signer, types.PermissionSetPermissions) { + return nil, sdkerrors.Wrapf(types.ErrPermissionDenied, "you cannot manage permissions in this subspace") + } + + // Set the group permissions and store the group + group.Permissions = msg.Permissions + k.SaveUserGroup(ctx, group) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, signer.String()), + ), + sdk.NewEvent( + types.ActionSetUserGroupPermissions, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeKeyUserGroupID, fmt.Sprintf("%d", msg.GroupID)), + ), + }) + + return &types.MsgSetUserGroupPermissionsResponse{}, nil +} + +// DeleteUserGroup defines a rpc method for MsgDeleteUserGroup +func (k msgServer) DeleteUserGroup(goCtx context.Context, msg *types.MsgDeleteUserGroup) (*types.MsgDeleteUserGroupResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + if !k.HasSubspace(ctx, msg.SubspaceID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + // Check if the group exists + if !k.HasUserGroup(ctx, msg.SubspaceID, msg.GroupID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group %d could not be found", msg.GroupID) + } + + signer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address: %s", msg.Signer) + } + + // Check for permissions + if !k.HasPermission(ctx, msg.SubspaceID, signer, types.PermissionManageGroups) { + return nil, sdkerrors.Wrap(types.ErrPermissionDenied, "you cannot delete user groups in this subspace") + } + + // Delete the group + k.Keeper.DeleteUserGroup(ctx, msg.SubspaceID, msg.GroupID) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer), + ), + sdk.NewEvent( + types.EventTypeDeleteUserGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeKeyUserGroupID, fmt.Sprintf("%d", msg.GroupID)), + ), + }) + + return &types.MsgDeleteUserGroupResponse{}, nil +} + +// AddUserToUserGroup defines a rpc method for MsgAddUserToUserGroup +func (k msgServer) AddUserToUserGroup(goCtx context.Context, msg *types.MsgAddUserToUserGroup) (*types.MsgAddUserToUserGroupResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + if !k.HasSubspace(ctx, msg.SubspaceID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + // Check if the group exists + if !k.HasUserGroup(ctx, msg.SubspaceID, msg.GroupID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group %d could not be found", msg.GroupID) + } + + signer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address: %s", msg.Signer) + } + + // Check the permissions + if !k.HasPermission(ctx, msg.SubspaceID, signer, types.PermissionSetPermissions) { + return nil, sdkerrors.Wrap(types.ErrPermissionDenied, "you cannot manage user group members in this subspace") + } + + user, err := sdk.AccAddressFromBech32(msg.User) + if err != nil { + return nil, err + } + + // Check if the user is already part of the group + if k.IsMemberOfGroup(ctx, msg.SubspaceID, msg.GroupID, user) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "user is already part of group %d", msg.GroupID) + } + + // Set the user group + err = k.AddUserToGroup(ctx, msg.SubspaceID, msg.GroupID, user) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer), + ), + sdk.NewEvent( + types.EventTypeAddUserToGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeKeyUserGroupID, fmt.Sprintf("%d", msg.GroupID)), + sdk.NewAttribute(types.AttributeKeyUser, msg.User), + ), + }) + + return &types.MsgAddUserToUserGroupResponse{}, nil +} + +// RemoveUserFromUserGroup defines a rpc method for MsgRemoveUserFromUserGroup +func (k msgServer) RemoveUserFromUserGroup(goCtx context.Context, msg *types.MsgRemoveUserFromUserGroup) (*types.MsgRemoveUserFromUserGroupResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + if !k.HasSubspace(ctx, msg.SubspaceID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + // Check if the group exists + if !k.HasUserGroup(ctx, msg.SubspaceID, msg.GroupID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "group %d could not be found", msg.GroupID) + } + + signer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address: %s", msg.Signer) + } + + // Check the permissions + if !k.HasPermission(ctx, msg.SubspaceID, signer, types.PermissionSetPermissions) { + return nil, sdkerrors.Wrap(types.ErrPermissionDenied, "you cannot manage user group members in this subspace") + } + + user, err := sdk.AccAddressFromBech32(msg.User) + if err != nil { + return nil, err + } + + // Check if the user is already part of the group + if !k.IsMemberOfGroup(ctx, msg.SubspaceID, msg.GroupID, user) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "user is not part of group %d", msg.GroupID) + } + + // Remove the user group + k.RemoveUserFromGroup(ctx, msg.SubspaceID, msg.GroupID, user) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer), + ), + sdk.NewEvent( + types.EventTypeRemoveUserFromGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeKeyUserGroupID, fmt.Sprintf("%d", msg.GroupID)), + sdk.NewAttribute(types.AttributeKeyUser, msg.User), + ), + }) + + return &types.MsgRemoveUserFromUserGroupResponse{}, nil +} + +// SetUserPermissions defines a rpc method for MsgSetUserPermissions +func (k msgServer) SetUserPermissions(goCtx context.Context, msg *types.MsgSetUserPermissions) (*types.MsgSetUserPermissionsResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + if !k.HasSubspace(ctx, msg.SubspaceID) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + user, err := sdk.AccAddressFromBech32(msg.User) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid user address: %s", msg.User) + } + + signer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address: %s", msg.Signer) + } + + // Check the permissions + if !k.HasPermission(ctx, msg.SubspaceID, signer, types.PermissionSetPermissions) { + return nil, sdkerrors.Wrapf(types.ErrPermissionDenied, "you cannot manage permissions in this subspace") + } + + // Set the permissions + if msg.Permissions == types.PermissionNothing { + // Remove the permission to clear the store if PermissionNothing is used + k.RemoveUserPermissions(ctx, msg.SubspaceID, user) + } else { + k.Keeper.SetUserPermissions(ctx, msg.SubspaceID, user, msg.Permissions) + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, signer.String()), + ), + sdk.NewEvent( + types.EventTypeSetUserPermissions, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeKeyUser, user.String()), + ), + }) + + return &types.MsgSetUserPermissionsResponse{}, nil +} diff --git a/x/subspaces/keeper/msg_server_test.go b/x/subspaces/keeper/msg_server_test.go new file mode 100644 index 0000000000..cc36b46797 --- /dev/null +++ b/x/subspaces/keeper/msg_server_test.go @@ -0,0 +1,1553 @@ +package keeper_test + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +func (suite *KeeperTestsuite) TestMsgServer_CreateSubspace() { + blockTime := time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC) + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgCreateSubspace + shouldErr bool + expResponse *types.MsgCreateSubspaceResponse + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "subspace id not set returns error", + msg: types.NewMsgCreateSubspace( + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + ), + shouldErr: true, + }, + { + name: "invalid subspace returns error", + store: func(ctx sdk.Context) { + store := ctx.KVStore(suite.storeKey) + store.Set(types.SubspaceIDKey, types.GetSubspaceIDBytes(1)) + }, + msg: types.NewMsgCreateSubspace( + "", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + ), + shouldErr: true, + }, + { + name: "first subspace is created properly", + store: func(ctx sdk.Context) { + store := ctx.KVStore(suite.storeKey) + store.Set(types.SubspaceIDKey, types.GetSubspaceIDBytes(1)) + }, + msg: types.NewMsgCreateSubspace( + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + ), + shouldErr: false, + expResponse: &types.MsgCreateSubspaceResponse{SubspaceID: 1}, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69"), + ), + sdk.NewEvent( + types.EventTypeCreateSubspace, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeKeySubspaceName, "Test subspace"), + sdk.NewAttribute(types.AttributeKeySubspaceCreator, "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69"), + sdk.NewAttribute(types.AttributeKeyCreationTime, "2020-01-01T12:00:00Z"), + ), + }, + check: func(ctx sdk.Context) { + // Make sure the subspace is stored + subspace, found := suite.k.GetSubspace(ctx, 1) + suite.Require().True(found) + suite.Require().Equal(types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), subspace) + + // Make sure the subspace id has increased + store := ctx.KVStore(suite.storeKey) + id := types.GetSubspaceIDFromBytes(store.Get(types.SubspaceIDKey)) + suite.Require().Equal(uint64(2), id) + }, + }, + { + name: "subspace has correct id when another subspace already exists", + store: func(ctx sdk.Context) { + store := ctx.KVStore(suite.storeKey) + store.Set(types.SubspaceIDKey, types.GetSubspaceIDBytes(1)) + + // Run the fist subspace creation message + msgServer := keeper.NewMsgServerImpl(suite.k) + _, err := msgServer.CreateSubspace(sdk.WrapSDKContext(ctx), types.NewMsgCreateSubspace( + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + )) + suite.Require().NoError(err) + }, + msg: types.NewMsgCreateSubspace( + "Another subspace", + "This is a second test subspace", + "cosmos1y4emx0mm4ncva9mnv9yvjrm7nrq3psvmwhk9ll", + "cosmos1y4emx0mm4ncva9mnv9yvjrm7nrq3psvmwhk9ll", + "cosmos1y4emx0mm4ncva9mnv9yvjrm7nrq3psvmwhk9ll", + ), + shouldErr: false, + expResponse: &types.MsgCreateSubspaceResponse{SubspaceID: 2}, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1y4emx0mm4ncva9mnv9yvjrm7nrq3psvmwhk9ll"), + ), + sdk.NewEvent( + types.EventTypeCreateSubspace, + sdk.NewAttribute(types.AttributeKeySubspaceID, "2"), + sdk.NewAttribute(types.AttributeKeySubspaceName, "Another subspace"), + sdk.NewAttribute(types.AttributeKeySubspaceCreator, "cosmos1y4emx0mm4ncva9mnv9yvjrm7nrq3psvmwhk9ll"), + sdk.NewAttribute(types.AttributeKeyCreationTime, "2020-01-01T12:00:00Z"), + ), + }, + check: func(ctx sdk.Context) { + // Make sure the subspace is stored + subspace, found := suite.k.GetSubspace(ctx, 2) + suite.Require().True(found) + suite.Require().Equal(types.NewSubspace( + 2, + "Another subspace", + "This is a second test subspace", + "cosmos1y4emx0mm4ncva9mnv9yvjrm7nrq3psvmwhk9ll", + "cosmos1y4emx0mm4ncva9mnv9yvjrm7nrq3psvmwhk9ll", + "cosmos1y4emx0mm4ncva9mnv9yvjrm7nrq3psvmwhk9ll", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), subspace) + + // Make sure the subspace id has increased + store := ctx.KVStore(suite.storeKey) + id := types.GetSubspaceIDFromBytes(store.Get(types.SubspaceIDKey)) + suite.Require().Equal(uint64(3), id) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + ctx = ctx.WithBlockTime(blockTime) + + if tc.store != nil { + tc.store(ctx) + } + + // Reset any event that might have been emitted during the setup + ctx = ctx.WithEventManager(sdk.NewEventManager()) + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + res, err := service.CreateSubspace(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expResponse, res) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestMsgServer_EditSubspace() { + blockTime := time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC) + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgEditSubspace + shouldErr bool + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "subspace not found returns error", + msg: types.NewMsgEditSubspace( + 1, + types.DoNotModify, + "This is a new description", + types.DoNotModify, + types.DoNotModify, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + check: func(ctx sdk.Context) { + _, found := suite.k.GetSubspace(ctx, 1) + suite.Require().False(found) + }, + }, + { + name: "missing permission returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + blockTime, + )) + }, + msg: types.NewMsgEditSubspace( + 1, + types.DoNotModify, + "This is a new description", + types.DoNotModify, + types.DoNotModify, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + check: func(ctx sdk.Context) { + subspace, found := suite.k.GetSubspace(ctx, 1) + suite.Require().True(found) + suite.Require().Equal(types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + blockTime, + ), subspace) + }, + }, + { + name: "invalid update returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + blockTime, + )) + }, + msg: types.NewMsgEditSubspace( + 1, + "", + "This is a new description", + types.DoNotModify, + types.DoNotModify, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + ), + shouldErr: true, + check: func(ctx sdk.Context) { + subspace, found := suite.k.GetSubspace(ctx, 1) + suite.Require().True(found) + suite.Require().Equal(types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + blockTime, + ), subspace) + }, + }, + { + name: "existing subspace is updated correctly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + blockTime, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionChangeInfo) + }, + msg: types.NewMsgEditSubspace( + 1, + "This is a new name", + "This is a new description", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: false, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5"), + ), + sdk.NewEvent( + types.EventTypeEditSubspace, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + ), + }, + check: func(ctx sdk.Context) { + subspace, found := suite.k.GetSubspace(ctx, 1) + suite.Require().True(found) + suite.Require().Equal(types.NewSubspace( + 1, + "This is a new name", + "This is a new description", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + blockTime, + ), subspace) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + ctx = ctx.WithBlockTime(blockTime) + + if tc.store != nil { + tc.store(ctx) + } + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + _, err := service.EditSubspace(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestMsgServer_DeleteSubspace() { + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgDeleteSubspace + shouldErr bool + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "subspace not found returns error", + msg: types.NewMsgDeleteSubspace(1, "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5"), + shouldErr: true, + check: func(ctx sdk.Context) { + _, found := suite.k.GetSubspace(ctx, 1) + suite.Require().False(found) + }, + }, + { + name: "missing permission returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + msg: types.NewMsgDeleteSubspace(1, "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5"), + shouldErr: true, + check: func(ctx sdk.Context) { + subspace, found := suite.k.GetSubspace(ctx, 1) + suite.Require().True(found) + suite.Require().Equal(types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), subspace) + }, + }, + { + name: "existing subspace is deleted correctly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionDeleteSubspace) + }, + msg: types.NewMsgDeleteSubspace(1, "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5"), + shouldErr: false, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5"), + ), + sdk.NewEvent( + types.EventTypeDeleteSubspace, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + ), + }, + check: func(ctx sdk.Context) { + exists := suite.k.HasSubspace(ctx, 1) + suite.Require().False(exists) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + _, err := service.DeleteSubspace(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestMsgServer_CreateUserGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgCreateUserGroup + shouldErr bool + expResponse *types.MsgCreateUserGroupResponse + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "non existing subspace returns error", + msg: types.NewMsgCreateUserGroup( + 1, + "group", + "description", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "user without permission returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + msg: types.NewMsgCreateUserGroup( + 1, + "group", + "description", + types.PermissionWrite, + "cosmos1y4emx0mm4ncva9mnv9yvjrm7nrq3psvmwhk9ll", + ), + shouldErr: true, + }, + { + name: "group is created properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + suite.k.SetGroupID(ctx, 1, 2) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionManageGroups) + }, + msg: types.NewMsgCreateUserGroup( + 1, + "another group", + "another description", + types.PermissionWrite, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: false, + expResponse: &types.MsgCreateUserGroupResponse{GroupID: 2}, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"), + ), + sdk.NewEvent( + types.EventTypeCreateUserGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeKeyUserGroupID, "2"), + ), + }, + check: func(ctx sdk.Context) { + suite.Require().True(suite.k.HasUserGroup(ctx, 1, 1)) + suite.Require().True(suite.k.HasUserGroup(ctx, 1, 2)) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + res, err := service.CreateUserGroup(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expResponse, res) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestMsgServer_EditUserGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgEditUserGroup + shouldErr bool + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "non existing subspace returns error", + msg: types.NewMsgEditUserGroup( + 1, + 1, + "Test group", + "This is a test group", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "group not found returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + msg: types.NewMsgEditUserGroup( + 1, + 1, + "Test group", + "This is a test group", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "no permission returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + msg: types.NewMsgEditUserGroup( + 1, + 1, + "Test group new name", + "This is a test group with a new name", + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "invalid update returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionManageGroups) + }, + msg: types.NewMsgEditUserGroup( + 1, + 1, + "", + "", + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "existing group is edited properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionManageGroups) + }, + msg: types.NewMsgEditUserGroup( + 1, + 1, + "Admins", + "Group of the admins of th subspace", + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: false, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"), + ), + sdk.NewEvent( + types.EventTypeEditUserGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeKeyUserGroupID, "1"), + ), + }, + check: func(ctx sdk.Context) { + group, found := suite.k.GetUserGroup(ctx, 1, 1) + suite.Require().True(found) + + suite.Require().Equal(types.NewUserGroup( + 1, + 1, + "Admins", + "Group of the admins of th subspace", + types.PermissionWrite, + ), group) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + _, err := service.EditUserGroup(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestMsgServer_SetUserGroupPermissions() { + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgSetUserGroupPermissions + shouldErr bool + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "subspace not found returns error", + msg: types.NewMsgSetUserGroupPermissions( + 1, + 1, + types.PermissionSetPermissions, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "group not found returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + msg: types.NewMsgSetUserGroupPermissions( + 1, + 1, + types.PermissionSetPermissions, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "no permission returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + msg: types.NewMsgSetUserGroupPermissions( + 1, + 1, + types.PermissionSetPermissions, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "existing group is deleted properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionSetPermissions) + }, + msg: types.NewMsgSetUserGroupPermissions( + 1, + 1, + types.PermissionSetPermissions, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: false, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"), + ), + sdk.NewEvent( + types.ActionSetUserGroupPermissions, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeKeyUserGroupID, "1"), + ), + }, + check: func(ctx sdk.Context) { + group, found := suite.k.GetUserGroup(ctx, 1, 1) + suite.Require().True(found) + + suite.Require().Equal(types.PermissionSetPermissions, group.Permissions) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + _, err := service.SetUserGroupPermissions(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestMsgServer_DeleteUserGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgDeleteUserGroup + shouldErr bool + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "subspace not found returns error", + msg: types.NewMsgDeleteUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "group not found returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + msg: types.NewMsgDeleteUserGroup( + 1, + 1, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "no permission returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + msg: types.NewMsgDeleteUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "existing group is deleted properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionManageGroups) + }, + msg: types.NewMsgDeleteUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: false, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"), + ), + sdk.NewEvent( + types.EventTypeDeleteUserGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeKeyUserGroupID, "1"), + ), + }, + check: func(ctx sdk.Context) { + hasGroup := suite.k.HasUserGroup(ctx, 1, 1) + suite.Require().False(hasGroup) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + _, err := service.DeleteUserGroup(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestMsgServer_AddUserToGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgAddUserToUserGroup + shouldErr bool + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "subspace not found returns error", + msg: types.NewMsgAddUserToUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "group not found returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + msg: types.NewMsgAddUserToUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "no permission returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + msg: types.NewMsgAddUserToUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "user already part of group returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, sdkAddr) + suite.Require().NoError(err) + }, + msg: types.NewMsgAddUserToUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "user not part of group is added correctly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionSetPermissions) + }, + msg: types.NewMsgAddUserToUserGroup( + 1, + 1, + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: false, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"), + ), + sdk.NewEvent( + types.EventTypeAddUserToGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeKeyUserGroupID, "1"), + sdk.NewAttribute(types.AttributeKeyUser, "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm"), + ), + }, + check: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + + result := suite.k.IsMemberOfGroup(ctx, 1, 1, sdkAddr) + suite.Require().True(result) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + _, err := service.AddUserToUserGroup(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestMsgServer_RemoveUserFromGroup() { + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgRemoveUserFromUserGroup + shouldErr bool + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "subspace not found returns error", + msg: types.NewMsgRemoveUserFromUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "group not found returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + msg: types.NewMsgRemoveUserFromUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "no permission returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + msg: types.NewMsgRemoveUserFromUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "user not part of group returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + }, + msg: types.NewMsgRemoveUserFromUserGroup( + 1, + 1, + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: true, + }, + { + name: "user part of group is removed correctly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionSetPermissions) + + sdkAddr, err = sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, sdkAddr) + suite.Require().NoError(err) + }, + msg: types.NewMsgRemoveUserFromUserGroup( + 1, + 1, + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: false, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"), + ), + sdk.NewEvent( + types.EventTypeRemoveUserFromGroup, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeKeyUserGroupID, "1"), + sdk.NewAttribute(types.AttributeKeyUser, "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm"), + ), + }, + check: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm") + suite.Require().NoError(err) + + result := suite.k.IsMemberOfGroup(ctx, 1, 1, sdkAddr) + suite.Require().False(result) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + _, err := service.RemoveUserFromUserGroup(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestMsgServer_SetUserPermissions() { + testCases := []struct { + name string + store func(ctx sdk.Context) + msg *types.MsgSetUserPermissions + shouldErr bool + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "subspace not found returns error", + msg: types.NewMsgSetUserPermissions( + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "no permission returns error", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + msg: types.NewMsgSetUserPermissions( + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + types.PermissionWrite, + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + ), + shouldErr: true, + }, + { + name: "permissions are set correctly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionSetPermissions) + }, + msg: types.NewMsgSetUserPermissions( + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + types.PermissionWrite, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + ), + shouldErr: false, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"), + ), + sdk.NewEvent( + types.EventTypeSetUserPermissions, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeKeyUser, "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"), + ), + }, + check: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53") + suite.Require().NoError(err) + permissions := suite.k.GetUserPermissions(ctx, 1, sdkAddr) + suite.Require().Equal(types.PermissionWrite, permissions) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + _, err := service.SetUserPermissions(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} diff --git a/x/subspaces/keeper/permissions.go b/x/subspaces/keeper/permissions.go new file mode 100644 index 0000000000..9210ca4d37 --- /dev/null +++ b/x/subspaces/keeper/permissions.go @@ -0,0 +1,108 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// SetUserPermissions sets the given permission for the specific user inside a single subspace +func (k Keeper) SetUserPermissions(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress, permissions types.Permission) { + store := ctx.KVStore(k.storeKey) + store.Set(types.UserPermissionStoreKey(subspaceID, user), types.MarshalPermission(permissions)) + + k.AfterUserPermissionSet(ctx, subspaceID, user, permissions) +} + +// HasPermission checks whether the specific user has the given permission inside a specific subspace +func (k Keeper) HasPermission(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress, permission types.Permission) bool { + // Get the subspace to make sure the request is valid + subspace, found := k.GetSubspace(ctx, subspaceID) + if !found { + return false + } + + specificPermissions := k.GetUserPermissions(ctx, subspaceID, user) + + // The owner of the subspaces has all the permissions by default + if subspace.Owner == user.String() { + return true + } + + // Get the group permissions + groupPermissions := k.GetGroupsInheritedPermissions(ctx, subspaceID, user) + + // Check the combination of the permissions + return types.CheckPermission(types.CombinePermissions(specificPermissions, groupPermissions), permission) +} + +// GetUserPermissions returns the permissions that are currently set inside +// the subspace with the given id for the given user +func (k Keeper) GetUserPermissions(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress) types.Permission { + store := ctx.KVStore(k.storeKey) + return types.UnmarshalPermission(store.Get(types.UserPermissionStoreKey(subspaceID, user))) +} + +// GetGroupsInheritedPermissions returns the permissions that the specified user +// has inherited from all the groups that they are part of. +func (k Keeper) GetGroupsInheritedPermissions(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress) types.Permission { + var permissions []types.Permission + k.IterateSubspaceGroups(ctx, subspaceID, func(index int64, group types.UserGroup) (stop bool) { + if k.IsMemberOfGroup(ctx, subspaceID, group.ID, user) { + permissions = append(permissions, group.Permissions) + } + return false + }) + return types.CombinePermissions(permissions...) +} + +// GetUsersWithPermission returns all the users that have a given permission inside the specified subspace +func (k Keeper) GetUsersWithPermission(ctx sdk.Context, subspaceID uint64, permission types.Permission) ([]sdk.AccAddress, error) { + subspace, found := k.GetSubspace(ctx, subspaceID) + if !found { + return nil, nil + } + + // The owner must always be included as they have all the permissions + ownerAddr, err := sdk.AccAddressFromBech32(subspace.Owner) + if err != nil { + return nil, err + } + + users := []sdk.AccAddress{ownerAddr} + + // Iterate over the various groups + k.IterateSubspaceGroups(ctx, subspaceID, func(index int64, group types.UserGroup) (stop bool) { + if !types.CheckPermission(group.Permissions, permission) { + // Return early if the group does not have the permission. We will check other groups anyway + return false + } + + // If the group has the permission, get all the members + k.IterateGroupMembers(ctx, subspaceID, group.ID, func(index int64, member sdk.AccAddress) (stop bool) { + users = append(users, member) + return false + }) + + return false + }) + + // Iterate over the various individually-set permissions + k.IterateSubspacePermissions(ctx, subspaceID, func(index int64, user sdk.AccAddress, userPerm types.Permission) (stop bool) { + if types.CheckPermission(userPerm, permission) { + users = append(users, user) + } + + return false + }) + + return users, nil +} + +// RemoveUserPermissions removes the permission for the given user inside the provided subspace +func (k Keeper) RemoveUserPermissions(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.UserPermissionStoreKey(subspaceID, user)) + + k.AfterUserPermissionRemoved(ctx, subspaceID, user) +} diff --git a/x/subspaces/keeper/permissions_test.go b/x/subspaces/keeper/permissions_test.go new file mode 100644 index 0000000000..c9cc61efc2 --- /dev/null +++ b/x/subspaces/keeper/permissions_test.go @@ -0,0 +1,550 @@ +package keeper_test + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +func (suite *KeeperTestsuite) TestKeeper_SetPermissions() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + user string + permission types.Permission + check func(ctx sdk.Context) + }{ + { + name: "permission is set properly for user", + subspaceID: 1, + user: "cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn", + permission: types.PermissionChangeInfo, + check: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn") + suite.Require().NoError(err) + + permission := suite.k.GetUserPermissions(ctx, 1, sdkAddr) + suite.Require().Equal(types.PermissionChangeInfo, permission) + }, + }, + { + name: "existing permission is overridden", + store: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn") + suite.Require().NoError(err) + + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionManageGroups) + }, + subspaceID: 1, + user: "cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn", + permission: types.PermissionWrite, + check: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn") + suite.Require().NoError(err) + + permission := suite.k.GetUserPermissions(ctx, 1, sdkAddr) + suite.Require().Equal(types.PermissionWrite, permission) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + sdkAddr, err := sdk.AccAddressFromBech32(tc.user) + suite.Require().NoError(err) + + suite.k.SetUserPermissions(ctx, tc.subspaceID, sdkAddr, tc.permission) + + if tc.check != nil { + tc.check(ctx) + } + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_HasPermission() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + user string + permission types.Permission + expResult bool + }{ + { + name: "subspace not found returns false", + subspaceID: 1, + user: "cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e", + expResult: false, + }, + { + name: "subspace owner returns always true", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + subspaceID: 1, + user: "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + permission: types.PermissionEverything, + expResult: true, + }, + { + name: "user with inherited permission returns true", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite|types.PermissionChangeInfo, + )) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + }, + subspaceID: 1, + user: "cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn", + permission: types.PermissionWrite, + expResult: true, + }, + { + name: "user with custom permission returns true", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite|types.PermissionChangeInfo, + )) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + + suite.k.SetUserPermissions(ctx, 1, userAddr, types.PermissionManageGroups) + }, + subspaceID: 1, + user: "cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn", + permission: types.PermissionManageGroups, + expResult: true, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + sdkAddr, err := sdk.AccAddressFromBech32(tc.user) + suite.Require().NoError(err) + + result := suite.k.HasPermission(ctx, tc.subspaceID, sdkAddr, tc.permission) + suite.Require().Equal(tc.expResult, result) + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_GetUserPermissions() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + user string + expPermissions types.Permission + }{ + { + name: "not found user returns PermissionNothing", + subspaceID: 1, + user: "cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e", + expPermissions: types.PermissionNothing, + }, + { + name: "found user returns the correct permission", + store: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1fgppppwfjszpts4shpsfv7n2xtchcdwhycuvvm") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionWrite|types.PermissionManageGroups) + }, + subspaceID: 1, + user: "cosmos1fgppppwfjszpts4shpsfv7n2xtchcdwhycuvvm", + expPermissions: types.PermissionWrite | types.PermissionManageGroups, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + sdkAddr, err := sdk.AccAddressFromBech32(tc.user) + suite.Require().NoError(err) + + permission := suite.k.GetUserPermissions(ctx, tc.subspaceID, sdkAddr) + suite.Require().Equal(tc.expPermissions, permission) + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_GetGroupsInheritedPermissions() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + user string + expPermissions types.Permission + }{ + { + name: "user in no group returns PermissionNothing", + subspaceID: 1, + user: "cosmos1fgppppwfjszpts4shpsfv7n2xtchcdwhycuvvm", + expPermissions: types.PermissionNothing, + }, + { + name: "user inside one group returns that group's permission", + store: func(ctx sdk.Context) { + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1fgppppwfjszpts4shpsfv7n2xtchcdwhycuvvm") + suite.Require().NoError(err) + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + }, + subspaceID: 1, + user: "cosmos1fgppppwfjszpts4shpsfv7n2xtchcdwhycuvvm", + expPermissions: types.PermissionWrite, + }, + { + name: "user inside multiple groups returns the combination of the various permissions", + store: func(ctx sdk.Context) { + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 2, + "Permission group", + "This is a permissions group", + types.PermissionSetPermissions|types.PermissionChangeInfo, + )) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1fgppppwfjszpts4shpsfv7n2xtchcdwhycuvvm") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, userAddr) + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 2, userAddr) + suite.Require().NoError(err) + }, + subspaceID: 1, + user: "cosmos1fgppppwfjszpts4shpsfv7n2xtchcdwhycuvvm", + expPermissions: types.PermissionWrite | types.PermissionChangeInfo | types.PermissionSetPermissions, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + userAddr, err := sdk.AccAddressFromBech32(tc.user) + suite.Require().NoError(err) + + permissions := suite.k.GetGroupsInheritedPermissions(ctx, tc.subspaceID, userAddr) + suite.Require().Equal(tc.expPermissions, permissions) + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_GetUsersWithPermissions() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + permissions types.Permission + shouldErr bool + expUsers []string + }{ + { + name: "subspace not found returns empty slice", + subspaceID: 1, + permissions: types.PermissionWrite, + shouldErr: false, + expUsers: nil, + }, + { + name: "no users found returns empty slice", + store: func(ctx sdk.Context) { + + }, + subspaceID: 1, + permissions: types.PermissionWrite, + shouldErr: false, + expUsers: nil, + }, + { + name: "users with permissions inherited from groups are returned properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, sdkAddr) + suite.Require().NoError(err) + }, + subspaceID: 1, + permissions: types.PermissionWrite, + shouldErr: false, + expUsers: []string{ + "cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", // Owner is always included + }, + }, + { + name: "users with individually set permissions are returned properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd") + suite.Require().NoError(err) + + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionWrite) + }, + subspaceID: 1, + permissions: types.PermissionWrite, + shouldErr: false, + expUsers: []string{ + "cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", // Owner is always included + }, + }, + { + name: "multiple users are returned properly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite|types.PermissionSetPermissions, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1xw69y2z3yf00rgfnly99628gn5c0x7fryyfv5e") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 1, sdkAddr) + suite.Require().NoError(err) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 2, + "Another test group", + "This is a second test group", + types.PermissionSetPermissions, + )) + + sdkAddr, err = sdk.AccAddressFromBech32("cosmos1e32dfqu7k9e5wj85cjtalqdd2zs6z7adgswnrn") + suite.Require().NoError(err) + + err = suite.k.AddUserToGroup(ctx, 1, 2, sdkAddr) + suite.Require().NoError(err) + + sdkAddr, err = sdk.AccAddressFromBech32("cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd") + suite.Require().NoError(err) + + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionWrite|types.PermissionChangeInfo) + + sdkAddr, err = sdk.AccAddressFromBech32("cosmos1f3e5dhpg3afanddld0kp6lkayz2qvuetf6hmv3") + suite.Require().NoError(err) + + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionChangeInfo) + }, + subspaceID: 1, + permissions: types.PermissionWrite, + shouldErr: false, + expUsers: []string{ + "cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd", + "cosmos1xw69y2z3yf00rgfnly99628gn5c0x7fryyfv5e", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", // Owner is always included + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + users, err := suite.k.GetUsersWithPermission(ctx, tc.subspaceID, tc.permissions) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Len(users, len(tc.expUsers)) + + for _, user := range users { + suite.Require().Contains(tc.expUsers, user.String()) + } + } + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_RemoveUserPermissions() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + user string + check func(ctx sdk.Context) + }{ + { + name: "permission is deleted for non existing user", + subspaceID: 1, + user: "cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn", + check: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn") + suite.Require().NoError(err) + + permission := suite.k.GetUserPermissions(ctx, 1, sdkAddr) + suite.Require().Equal(types.PermissionNothing, permission) + }, + }, + { + name: "permission is deleted for existing user", + store: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn") + suite.Require().NoError(err) + + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionManageGroups) + }, + subspaceID: 1, + user: "cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn", + check: func(ctx sdk.Context) { + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1fz49f2njk28ue8geqm63g4zzsm97lahqa9vmwn") + suite.Require().NoError(err) + + permission := suite.k.GetUserPermissions(ctx, 1, sdkAddr) + suite.Require().Equal(types.PermissionNothing, permission) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + sdkAddr, err := sdk.AccAddressFromBech32(tc.user) + suite.Require().NoError(err) + + suite.k.RemoveUserPermissions(ctx, tc.subspaceID, sdkAddr) + + if tc.check != nil { + tc.check(ctx) + } + }) + } +} diff --git a/x/subspaces/keeper/subspaces.go b/x/subspaces/keeper/subspaces.go new file mode 100644 index 0000000000..472e397421 --- /dev/null +++ b/x/subspaces/keeper/subspaces.go @@ -0,0 +1,101 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// SetSubspaceID sets the new subspace id to the store +func (k Keeper) SetSubspaceID(ctx sdk.Context, subspaceID uint64) { + store := ctx.KVStore(k.storeKey) + store.Set(types.SubspaceIDKey, types.GetSubspaceIDBytes(subspaceID)) +} + +// GetSubspaceID gets the highest subspace id +func (k Keeper) GetSubspaceID(ctx sdk.Context) (subspaceID uint64, err error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.SubspaceIDKey) + if bz == nil { + return 0, sdkerrors.Wrap(types.ErrInvalidGenesis, "initial subspace ID hasn't been set") + } + + subspaceID = types.GetSubspaceIDFromBytes(bz) + return subspaceID, nil +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SaveSubspace saves the given subspace inside the current context. +func (k Keeper) SaveSubspace(ctx sdk.Context, subspace types.Subspace) { + store := ctx.KVStore(k.storeKey) + + // Store the subspace + store.Set(types.SubspaceKey(subspace.ID), k.cdc.MustMarshal(&subspace)) + + // If the initial group id does not exist, create it now + groupIDKey := types.GroupIDStoreKey(subspace.ID) + if !store.Has(groupIDKey) { + store.Set(groupIDKey, types.GetGroupIDBytes(1)) + } + + k.Logger(ctx).Info("subspace saved", "id", subspace.ID) + k.AfterSubspaceSaved(ctx, subspace.ID) +} + +// HasSubspace tells whether the given subspace exists or not +func (k Keeper) HasSubspace(ctx sdk.Context, subspaceID uint64) bool { + store := ctx.KVStore(k.storeKey) + return store.Has(types.SubspaceKey(subspaceID)) +} + +// GetSubspace returns the subspace associated with the given id. +// If there is no subspace associated with the given id the function will return an empty subspace and false. +func (k Keeper) GetSubspace(ctx sdk.Context, subspaceID uint64) (subspace types.Subspace, found bool) { + store := ctx.KVStore(k.storeKey) + + key := types.SubspaceKey(subspaceID) + if !store.Has(key) { + return types.Subspace{}, false + } + + k.cdc.MustUnmarshal(store.Get(key), &subspace) + return subspace, true +} + +// DeleteSubspace allows to delete the subspace with the given id +func (k Keeper) DeleteSubspace(ctx sdk.Context, subspaceID uint64) { + // Delete the subspace + store := ctx.KVStore(k.storeKey) + store.Delete(types.SubspaceKey(subspaceID)) + + // Delete the group id + store.Delete(types.GroupIDStoreKey(subspaceID)) + + // Delete all user groups + var groups []uint32 + k.IterateSubspaceGroups(ctx, subspaceID, func(_ int64, group types.UserGroup) (stop bool) { + groups = append(groups, group.ID) + return false + }) + + for _, groupID := range groups { + k.DeleteUserGroup(ctx, subspaceID, groupID) + } + + // Delete all the permissions for this subspace + var members []sdk.AccAddress + k.IterateSubspacePermissions(ctx, subspaceID, func(_ int64, user sdk.AccAddress, _ types.Permission) (stop bool) { + members = append(members, user) + return false + }) + + for _, member := range members { + k.RemoveUserPermissions(ctx, subspaceID, member) + } + + // Log the subspace deletion + k.Logger(ctx).Info("subspace deleted", "id", subspaceID) + k.AfterSubspaceDeleted(ctx, subspaceID) +} diff --git a/x/subspaces/keeper/subspaces_test.go b/x/subspaces/keeper/subspaces_test.go new file mode 100644 index 0000000000..13c6d66ffa --- /dev/null +++ b/x/subspaces/keeper/subspaces_test.go @@ -0,0 +1,349 @@ +package keeper_test + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +func (suite *KeeperTestsuite) TestKeeper_SetSubspaceID() { + testCases := []struct { + name string + id uint64 + check func(ctx sdk.Context) + }{ + { + name: "zero subspace id", + id: 0, + check: func(ctx sdk.Context) { + store := ctx.KVStore(suite.storeKey) + suite.Require().Equal(uint64(0), types.GetSubspaceIDFromBytes(store.Get(types.SubspaceIDKey))) + }, + }, + { + name: "non-zero subspace id", + id: 5, + check: func(ctx sdk.Context) { + store := ctx.KVStore(suite.storeKey) + suite.Require().Equal(uint64(5), types.GetSubspaceIDFromBytes(store.Get(types.SubspaceIDKey))) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + + suite.k.SetSubspaceID(ctx, tc.id) + if tc.check != nil { + tc.check(ctx) + } + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_GetSubspaceID() { + testCases := []struct { + name string + store func(ctx sdk.Context) + shouldErr bool + expID uint64 + }{ + { + name: "subspace id not set", + shouldErr: true, + }, + { + name: "subspace id set", + store: func(ctx sdk.Context) { + store := ctx.KVStore(suite.storeKey) + store.Set(types.SubspaceIDKey, types.GetSubspaceIDBytes(1)) + }, + shouldErr: false, + expID: 1, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + id, err := suite.k.GetSubspaceID(ctx) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expID, id) + } + }) + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +func (suite *KeeperTestsuite) TestKeeper_SaveSubspace() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspace types.Subspace + check func(ctx sdk.Context) + }{ + { + name: "non existing subspace is stored properly", + subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + check: func(ctx sdk.Context) { + subspace, found := suite.k.GetSubspace(ctx, 1) + suite.Require().True(found) + suite.Require().Equal(types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), subspace) + }, + }, + { + name: "existing subspace is replaced correctly", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + subspace: types.NewSubspace( + 1, + "Test subspace with another name and owner", + "This is a test subspace with a changed description", + "cosmos1fgppppwfjszpts4shpsfv7n2xtchcdwhycuvvm", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + check: func(ctx sdk.Context) { + subspace, found := suite.k.GetSubspace(ctx, 1) + suite.Require().True(found) + suite.Require().Equal(types.NewSubspace( + 1, + "Test subspace with another name and owner", + "This is a test subspace with a changed description", + "cosmos1fgppppwfjszpts4shpsfv7n2xtchcdwhycuvvm", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), subspace) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + suite.k.SaveSubspace(ctx, tc.subspace) + + if tc.check != nil { + tc.check(ctx) + } + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_HasSubspace() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + expResult bool + }{ + { + name: "not found subspace returns false", + subspaceID: 1, + expResult: false, + }, + { + name: "found subspace returns the correct data", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + subspaceID: 1, + expResult: true, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + result := suite.k.HasSubspace(ctx, tc.subspaceID) + suite.Require().Equal(tc.expResult, result) + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_GetSubspace() { + testCases := []struct { + name string + store func(ctx sdk.Context) + id uint64 + expSubspace types.Subspace + expFound bool + }{ + { + name: "not found subspace returns false", + id: 1, + expFound: false, + }, + { + name: "found subspace returns the correct data", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + }, + id: 1, + expFound: true, + expSubspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + subspace, found := suite.k.GetSubspace(ctx, tc.id) + suite.Require().Equal(tc.expFound, found) + if tc.expFound { + suite.Require().Equal(tc.expSubspace, subspace) + } + }) + } +} + +func (suite *KeeperTestsuite) TestKeeper_DeleteSubspace() { + testCases := []struct { + name string + store func(ctx sdk.Context) + subspaceID uint64 + check func(ctx sdk.Context) + }{ + { + name: "non existing subspace is deleted properly", + subspaceID: 1, + check: func(ctx sdk.Context) { + found := suite.k.HasSubspace(ctx, 1) + suite.Require().False(found) + }, + }, + { + name: "existing subspace is deleted and all groups and permissions are removed", + store: func(ctx sdk.Context) { + suite.k.SaveSubspace(ctx, types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + )) + + suite.k.SaveUserGroup(ctx, types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + )) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e") + suite.Require().NoError(err) + suite.k.SetUserPermissions(ctx, 1, sdkAddr, types.PermissionWrite) + }, + subspaceID: 1, + check: func(ctx sdk.Context) { + found := suite.k.HasSubspace(ctx, 1) + suite.Require().False(found) + + groups := suite.k.GetSubspaceGroups(ctx, 1) + suite.Require().Empty(groups) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e") + suite.Require().NoError(err) + permission := suite.k.GetUserPermissions(ctx, 1, sdkAddr) + suite.Require().Equal(types.PermissionNothing, permission) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + suite.k.DeleteSubspace(ctx, tc.subspaceID) + if tc.check != nil { + tc.check(ctx) + } + }) + } +} diff --git a/x/subspaces/module.go b/x/subspaces/module.go new file mode 100644 index 0000000000..a1d73ac769 --- /dev/null +++ b/x/subspaces/module.go @@ -0,0 +1,206 @@ +package subspaces + +import ( + "context" + "encoding/json" + "fmt" + "math/rand" + + "github.com/desmos-labs/desmos/v2/x/subspaces/simulation" + + "github.com/desmos-labs/desmos/v2/x/subspaces/client/cli" + + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" +) + +// type check to ensure the interface is properly implemented +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleSimulation = AppModule{} +) + +// AppModuleBasic defines the basic application module used by the subspaces module. +type AppModuleBasic struct { + cdc codec.Codec +} + +// Name returns the subspaces module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec registers the subspaces module's types for the given codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// DefaultGenesis returns default genesis state as raw bytes for the subspaces module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the subspaces module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { + var data types.GenesisState + if err := cdc.UnmarshalJSON(bz, &data); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + return types.ValidateGenesis(&data) +} + +// RegisterRESTRoutes registers the REST routes for the subspaces module. +func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the subspaces module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetTxCmd returns the root tx command for the subspaces module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.NewTxCmd() +} + +// GetQueryCmd returns the root query command for the subspaces module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// RegisterInterfaces registers interfaces and implementations of the subspaces module. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// -------------------------------------------------------------------------------------------------------------------- + +// AppModule implements an application module for the subspaces module. +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper + ak authkeeper.AccountKeeper + bk bankkeeper.Keeper +} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// NewAppModule creates a new AppModule Object +func NewAppModule( + cdc codec.Codec, keeper keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{cdc: cdc}, + keeper: keeper, + ak: ak, + bk: bk, + } +} + +// Name returns the subspaces module's name. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants performs a no-op. +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + keeper.RegisterInvariants(ir, am.keeper) +} + +// Route returns the message routing key for the subspaces module. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, NewHandler(am.keeper)) +} + +// NewHandler returns an sdk.Handler for the subspaces module. +func (am AppModule) NewHandler() sdk.Handler { + return NewHandler(am.keeper) +} + +// QuerierRoute returns the subspaces module's querier route name. +func (am AppModule) QuerierRoute() string { + return types.QuerierRoute +} + +// LegacyQuerierHandler returns the subspaces module sdk.Querier. +func (am AppModule) LegacyQuerierHandler(_ *codec.LegacyAmino) sdk.Querier { + return nil +} + +// InitGenesis performs genesis initialization for the subspaces module. +// It returns no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + cdc.MustUnmarshalJSON(data, &genesisState) + am.keeper.InitGenesis(ctx, genesisState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the exported genesis state as raw bytes for the +// subspaces module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := am.keeper.ExportGenesis(ctx) + return cdc.MustMarshalJSON(gs) +} + +// ConsensusVersion implements AppModule. +func (AppModule) ConsensusVersion() uint64 { + return 1 +} + +// BeginBlock returns the begin blocker for the subspaces module. +func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { +} + +// EndBlock returns the end blocker for the subspaces module. It returns no validator +// updates. +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// AppModuleSimulation defines the module simulation functions used by the subspaces module. +type AppModuleSimulation struct{} + +// GenerateGenesisState creates a randomized GenState of the bank module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizeGenState(simState) +} + +// ProposalContents doesn't return any content functions for governance proposals. +func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized subspaces param changes for the simulator. +func (AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange { + return nil +} + +// RegisterStoreDecoder performs a no-op. +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { + sdr[types.ModuleName] = simulation.NewDecodeStore(am.cdc) +} + +// WeightedOperations returns the all the subspaces module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + return simulation.WeightedOperations(simState.AppParams, simState.Cdc, am.keeper, am.ak, am.bk) +} diff --git a/x/subspaces/simulation/decoder.go b/x/subspaces/simulation/decoder.go new file mode 100644 index 0000000000..792b109598 --- /dev/null +++ b/x/subspaces/simulation/decoder.go @@ -0,0 +1,55 @@ +package simulation + +import ( + "bytes" + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/kv" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// NewDecodeStore returns a new decoder that unmarshals the KVPair's Value +// to the corresponding subspaces type +func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string { + return func(kvA, kvB kv.Pair) string { + switch { + case bytes.HasPrefix(kvA.Key, types.SubspaceIDKey): + var idA, idB uint64 + idA = types.GetSubspaceIDFromBytes(kvA.Value) + idB = types.GetSubspaceIDFromBytes(kvB.Value) + return fmt.Sprintf("SubspaceIDA: %d\nSubspaceIDB: %d\n", idA, idB) + + case bytes.HasPrefix(kvA.Key, types.SubspacePrefix): + var subspaceA, subspaceB types.Subspace + cdc.MustUnmarshal(kvA.Value, &subspaceA) + cdc.MustUnmarshal(kvB.Value, &subspaceB) + return fmt.Sprintf("SubspaceA: %s\nSubspaceB: %s\n", subspaceA.String(), subspaceB.String()) + + case bytes.HasPrefix(kvA.Key, types.GroupIDPrefix): + var groupIDA, groupIDB uint32 + groupIDA = types.GetGroupIDFromBytes(kvA.Value) + groupIDB = types.GetGroupIDFromBytes(kvB.Value) + return fmt.Sprintf("GroupIDA: %d\nGroupIDB: %d\n", groupIDA, groupIDB) + + case bytes.HasPrefix(kvA.Key, types.GroupsPrefix): + var groupA, groupB types.UserGroup + cdc.MustUnmarshal(kvA.Value, &groupA) + cdc.MustUnmarshal(kvB.Value, &groupB) + return fmt.Sprintf("GroupA: %s\nGroupB: %s\n", &groupA, &groupB) + + case bytes.HasPrefix(kvA.Key, types.GroupMembersStorePrefix): + return fmt.Sprintf("GroupMemberKeyA: %s\nGroupMemberKeyB: %s\n", kvA.Key, kvB.Key) + + case bytes.HasPrefix(kvA.Key, types.UserPermissionsStorePrefix): + var permissionA, permissionB uint32 + permissionA = types.UnmarshalPermission(kvA.Value) + permissionB = types.UnmarshalPermission(kvB.Value) + return fmt.Sprintf("PermissionKeyA: %d\nPermissionKeyB: %d\n", permissionA, permissionB) + + default: + panic(fmt.Sprintf("unexpected %s key %X (%s)", types.ModuleName, kvA.Key, kvA.Key)) + } + } +} diff --git a/x/subspaces/simulation/decoder_test.go b/x/subspaces/simulation/decoder_test.go new file mode 100644 index 0000000000..a39705af92 --- /dev/null +++ b/x/subspaces/simulation/decoder_test.go @@ -0,0 +1,107 @@ +package simulation_test + +import ( + "fmt" + "testing" + "time" + + "github.com/desmos-labs/desmos/v2/x/subspaces/simulation" + + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v2/app" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +func TestDecodeStore(t *testing.T) { + cdc, _ := app.MakeCodecs() + decoder := simulation.NewDecodeStore(cdc) + + sdkAddr, err := sdk.AccAddressFromBech32("cosmos19r59nc7wfgc5gjnu5ga5yztkvr5qssj24krx2f") + require.NoError(t, err) + + subspace := types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ) + group := types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ) + + userAddr, err := sdk.AccAddressFromBech32("cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e") + require.NoError(t, err) + + kvPairs := kv.Pairs{Pairs: []kv.Pair{ + { + Key: types.SubspaceIDKey, + Value: types.GetSubspaceIDBytes(1), + }, + { + Key: types.SubspaceKey(subspace.ID), + Value: cdc.MustMarshal(&subspace), + }, + { + Key: types.GroupIDStoreKey(1), + Value: types.GetGroupIDBytes(1), + }, + { + Key: types.GroupStoreKey(1, 1), + Value: cdc.MustMarshal(&group), + }, + { + Key: types.GroupMemberStoreKey(1, 1, sdkAddr), + Value: []byte{0x01}, + }, + { + Key: types.UserPermissionStoreKey(1, userAddr), + Value: types.MarshalPermission(types.PermissionWrite), + }, + { + Key: []byte("Unknown key"), + Value: nil, + }, + }} + + testCases := []struct { + name string + expectedLog string + }{ + {"Subspace ID", fmt.Sprintf("SubspaceIDA: %d\nSubspaceIDB: %d\n", + 1, 1)}, + {"Subspace", fmt.Sprintf("SubspaceA: %s\nSubspaceB: %s\n", + subspace.String(), subspace.String())}, + {"Group ID", fmt.Sprintf("GroupIDA: %d\nGroupIDB: %d\n", + 1, 1)}, + {"Group", fmt.Sprintf("GroupA: %s\nGroupB: %s\n", + group.String(), group.String())}, + {"Group member", fmt.Sprintf("GroupMemberKeyA: %s\nGroupMemberKeyB: %s\n", + types.GroupMemberStoreKey(1, 1, sdkAddr), types.GroupMemberStoreKey(1, 1, sdkAddr))}, + {"Permission", fmt.Sprintf("PermissionKeyA: %d\nPermissionKeyB: %d\n", + types.PermissionWrite, types.PermissionWrite)}, + {"other", ""}, + } + + for i, tc := range testCases { + i, tc := i, tc + t.Run(tc.name, func(t *testing.T) { + switch i { + case len(testCases) - 1: + require.Panics(t, func() { decoder(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tc.name) + default: + require.Equal(t, tc.expectedLog, decoder(kvPairs.Pairs[i], kvPairs.Pairs[i]), tc.name) + } + }) + } +} diff --git a/x/subspaces/simulation/genesis.go b/x/subspaces/simulation/genesis.go new file mode 100644 index 0000000000..aa6d059223 --- /dev/null +++ b/x/subspaces/simulation/genesis.go @@ -0,0 +1,224 @@ +package simulation + +// DONTCOVER + +import ( + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/types/module" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// RandomizeGenState generates a random GenesisState for subspaces +func RandomizeGenState(simState *module.SimulationState) { + subspaces := randomSubspaces(simState.Rand, simState.Accounts) + groups, members := randomUserGroups(simState.Rand, simState.Accounts, subspaces) + acl := randomACL(simState.Rand, simState.Accounts, subspaces) + initialSubspaceID, genSubspaces := getInitialIDs(subspaces, groups) + + // Create the genesis and sanitize it + subspacesGenesis := types.NewGenesisState(initialSubspaceID, genSubspaces, acl, groups, members) + subspacesGenesis = sanitizeGenesis(subspacesGenesis) + + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(subspacesGenesis) +} + +// randomSubspaces returns randomly generated genesis account +func randomSubspaces(r *rand.Rand, accs []simtypes.Account) (subspaces []types.Subspace) { + subspacesNumber := r.Intn(100) + subspaces = make([]types.Subspace, subspacesNumber) + for index := 0; index < subspacesNumber; index++ { + subspaces[index] = GenerateRandomSubspace(r, accs) + } + return subspaces +} + +// randomUserGroups generates random slice of user group details +func randomUserGroups( + r *rand.Rand, accounts []simtypes.Account, subspaces []types.Subspace, +) (groups []types.UserGroup, membersEntries []types.UserGroupMembersEntry) { + groupsNumber := r.Intn(30) + + groups = make([]types.UserGroup, groupsNumber) + membersEntries = make([]types.UserGroupMembersEntry, groupsNumber) + + for i := 0; i < groupsNumber; i++ { + subspace, _ := RandomSubspace(r, subspaces) + groupID := uint32(i + 1) + + // Get a random permission + permission := RandomPermission(r, []types.Permission{ + types.PermissionNothing, + types.PermissionWrite, + types.PermissionManageGroups, + types.PermissionEverything, + }) + + // Build the group details + groups[i] = types.NewUserGroup(subspace.ID, groupID, RandomName(r), RandomDescription(r), permission) + + // Get a random number of members + membersNumber := r.Intn(5) + members := make([]string, membersNumber) + for j := 0; j < membersNumber; j++ { + members[j] = RandomAccount(r, accounts).Address.String() + } + members = sanitizeStrings(members) + + // Build the members details + membersEntries[i] = types.NewUserGroupMembersEntry(subspace.ID, groupID, members) + } + + return groups, membersEntries +} + +// getInitialIDs returns the initial subspace id and various initial group ids given the slice of subspaces and groups +func getInitialIDs( + subspaces []types.Subspace, groups []types.UserGroup, +) (initialSubspaceID uint64, genSubspaces []types.GenesisSubspace) { + initialGroupIDS := map[uint64]uint32{} + for _, subspace := range subspaces { + if subspace.ID > initialSubspaceID { + initialSubspaceID = subspace.ID + } + + // Get the max group id + maxGroupID := uint32(0) + for _, group := range groups { + if group.SubspaceID == subspace.ID && group.ID > maxGroupID { + maxGroupID = group.ID + } + } + + // Get the initial group id for this subspace + initialGroupIDS[subspace.ID] = maxGroupID + 1 + } + + genSubspaces = make([]types.GenesisSubspace, len(subspaces)) + for i, subspace := range subspaces { + genSubspaces[i] = types.NewGenesisSubspace(subspace, initialGroupIDS[subspace.ID]) + } + + return initialSubspaceID, genSubspaces +} + +// randomACL generates a random slice of ACL entries +func randomACL(r *rand.Rand, accounts []simtypes.Account, subspaces []types.Subspace) (entries []types.ACLEntry) { + aclEntriesNumber := r.Intn(40) + entries = make([]types.ACLEntry, aclEntriesNumber) + for index := 0; index < aclEntriesNumber; index++ { + subspace, _ := RandomSubspace(r, subspaces) + target := RandomAccount(r, accounts).Address.String() + + // Get a random permission + permission := RandomPermission(r, []types.Permission{ + types.PermissionNothing, + types.PermissionWrite, + types.PermissionManageGroups, + types.PermissionEverything, + }) + + // Crete the entry + entries[index] = types.NewACLEntry(subspace.ID, target, permission) + } + + return entries +} + +// -------------------------------------------------------------------------------------------------------------------- + +// sanitizeGenesis sanitizes the given genesis by removing all the double subspaces, +// groups or ACL entries that might be there +func sanitizeGenesis(genesis *types.GenesisState) *types.GenesisState { + return types.NewGenesisState( + genesis.InitialSubspaceID, + sanitizeSubspaces(genesis.Subspaces), + sanitizeACLEntry(genesis.ACL), + sanitizeUserGroups(genesis.UserGroups), + genesis.UserGroupsMembers, + ) +} + +// sanitizeSubspaces sanitizes the given slice by removing all the double subspaces +func sanitizeSubspaces(slice []types.GenesisSubspace) []types.GenesisSubspace { + ids := map[uint64]int{} + for _, value := range slice { + ids[value.Subspace.ID] = 1 + } + + var unique []types.GenesisSubspace + for id := range ids { + SubspaceLoop: + for _, subspace := range slice { + if id == subspace.Subspace.ID { + unique = append(unique, subspace) + break SubspaceLoop + } + } + } + + return unique +} + +// sanitizeUserGroups sanitizes the given slice by removing all the double groups +func sanitizeUserGroups(slice []types.UserGroup) []types.UserGroup { + groups := map[string]int{} + for _, value := range slice { + groups[fmt.Sprintf("%d%s", value.SubspaceID, value.Name)] = 1 + } + + var unique []types.UserGroup + for id := range groups { + EntryLoop: + for _, group := range slice { + if id == fmt.Sprintf("%d%s", group.SubspaceID, group.Name) { + unique = append(unique, group) + break EntryLoop + } + } + } + + return unique +} + +// sanitizeSubspaces sanitizes the given slice by removing all the double entries +func sanitizeACLEntry(slice []types.ACLEntry) []types.ACLEntry { + entries := map[string]int{} + for _, value := range slice { + entries[fmt.Sprintf("%d%s", value.SubspaceID, value.User)] = 1 + } + + var unique []types.ACLEntry + for id := range entries { + EntryLoop: + for _, entry := range slice { + if id == fmt.Sprintf("%d%s", entry.SubspaceID, entry.User) { + unique = append(unique, entry) + break EntryLoop + } + } + } + + return unique +} + +// sanitizeStrings sanitizes the given slice by removing all duplicated values +func sanitizeStrings(slice []string) []string { + values := map[string]int{} + for _, value := range slice { + values[value] = 1 + } + + count := 0 + unique := make([]string, len(values)) + for value := range values { + unique[count] = value + count++ + } + + return unique +} diff --git a/x/subspaces/simulation/operations.go b/x/subspaces/simulation/operations.go new file mode 100644 index 0000000000..46f55b902a --- /dev/null +++ b/x/subspaces/simulation/operations.go @@ -0,0 +1,153 @@ +package simulation + +// DONTCOVER + +import ( + "math/rand" + + "github.com/cosmos/cosmos-sdk/codec" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + sim "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/desmos-labs/desmos/v2/app/params" + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" +) + +// Simulation operation weights constants +// #nosec G101 -- This is a false positive +const ( + OpWeightMsgCreateSubspace = "op_weight_msg_create_subspace" + OpWeightMsgEditSubspace = "op_weight_msg_edit_subspace" + OpWeightMsgDeleteSubspace = "op_weight_msg_delete_subspace" + OpWeightMsgCreateUserGroup = "op_weight_msg_create_user_group" + OpWeightMsgEditUserGroup = "op_weight_msg_edit_user_group" + OpWeightMsgSetUserGroupPermissions = "op_weight_msg_set_user_group_permissions" + OpWeightMsgDeleteUserGroup = "op_weight_msg_delete_user_group" + OpWeightMsgAddUserToUserGroup = "op_weight_msg_add_user_to_user_group" + OpWeightMsgRemoveUserFromUserGroup = "op_weight_msg_remove_user_from_user_group" + OpWeightMsgSetUserPermissions = "op_weight_msg_set_user_permissions" + + DefaultGasValue = 200_000 +) + +// WeightedOperations returns all the operations from the module with their respective weights +func WeightedOperations( + appParams simtypes.AppParams, cdc codec.JSONCodec, + k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) sim.WeightedOperations { + + var weightMsgCreateSubspace int + appParams.GetOrGenerate(cdc, OpWeightMsgCreateSubspace, &weightMsgCreateSubspace, nil, + func(_ *rand.Rand) { + weightMsgCreateSubspace = params.DefaultWeightMsgCreateSubspace + }, + ) + + var weightMsgEditSubspace int + appParams.GetOrGenerate(cdc, OpWeightMsgEditSubspace, &weightMsgEditSubspace, nil, + func(_ *rand.Rand) { + weightMsgEditSubspace = params.DefaultWeightMsgEditSubspace + }, + ) + + var weightMsgDeleteSubspace int + appParams.GetOrGenerate(cdc, OpWeightMsgDeleteSubspace, &weightMsgDeleteSubspace, nil, + func(_ *rand.Rand) { + weightMsgDeleteSubspace = params.DefaultWeightMsgDeleteSubspace + }, + ) + + var weightMsgCreateUserGroup int + appParams.GetOrGenerate(cdc, OpWeightMsgCreateUserGroup, &weightMsgCreateUserGroup, nil, + func(_ *rand.Rand) { + weightMsgCreateUserGroup = params.DefaultWeightMsgCreateUserGroup + }, + ) + + var weightMsgEditUserGroup int + appParams.GetOrGenerate(cdc, OpWeightMsgEditUserGroup, &weightMsgEditUserGroup, nil, + func(_ *rand.Rand) { + weightMsgEditUserGroup = params.DefaultWeightMsgEditUserGroup + }, + ) + + var weightMsgSetUserGroupPermissions int + appParams.GetOrGenerate(cdc, OpWeightMsgSetUserGroupPermissions, &weightMsgSetUserGroupPermissions, nil, + func(_ *rand.Rand) { + weightMsgSetUserGroupPermissions = params.DefaultWeightMsgSetUserGroupPermissions + }, + ) + + var weightMsgDeleteUserGroup int + appParams.GetOrGenerate(cdc, OpWeightMsgDeleteUserGroup, &weightMsgDeleteUserGroup, nil, + func(_ *rand.Rand) { + weightMsgDeleteUserGroup = params.DefaultWeightMsgDeleteUserGroup + }, + ) + + var weightMsgAddUserToUserGroup int + appParams.GetOrGenerate(cdc, OpWeightMsgAddUserToUserGroup, &weightMsgAddUserToUserGroup, nil, + func(_ *rand.Rand) { + weightMsgAddUserToUserGroup = params.DefaultWeightMsgAddUserToUserGroup + }, + ) + + var weightMsgRemoveUserFromUserGroup int + appParams.GetOrGenerate(cdc, OpWeightMsgRemoveUserFromUserGroup, &weightMsgRemoveUserFromUserGroup, nil, + func(_ *rand.Rand) { + weightMsgRemoveUserFromUserGroup = params.DefaultWeightMsgRemoveUserFromUserGroup + }, + ) + + var weightMsgSetUserPermissions int + appParams.GetOrGenerate(cdc, OpWeightMsgSetUserPermissions, &weightMsgSetUserPermissions, nil, + func(_ *rand.Rand) { + weightMsgSetUserPermissions = params.DefaultWeightMsgSetUserPermissions + }, + ) + + return sim.WeightedOperations{ + sim.NewWeightedOperation( + weightMsgCreateSubspace, + SimulateMsgCreateSubspace(ak, bk), + ), + sim.NewWeightedOperation( + weightMsgEditSubspace, + SimulateMsgEditSubspace(k, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgDeleteSubspace, + SimulateMsgDeleteSubspace(k, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgCreateUserGroup, + SimulateMsgCreateUserGroup(k, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgEditUserGroup, + SimulateMsgEditUserGroup(k, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgSetUserGroupPermissions, + SimulateMsgSetUserGroupPermissions(k, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgDeleteUserGroup, + SimulateMsgDeleteUserGroup(k, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgAddUserToUserGroup, + SimulateMsgAddUserToUserGroup(k, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgRemoveUserFromUserGroup, + SimulateMsgRemoveUserFromUserGroup(k, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgSetUserPermissions, + SimulateMsgSetUserPermissions(k, ak, bk), + ), + } +} diff --git a/x/subspaces/simulation/operations_groups.go b/x/subspaces/simulation/operations_groups.go new file mode 100644 index 0000000000..719c11d9b0 --- /dev/null +++ b/x/subspaces/simulation/operations_groups.go @@ -0,0 +1,416 @@ +package simulation + +// DONTCOVER + +import ( + "math/rand" + + "github.com/desmos-labs/desmos/v2/testutil/simtesting" + + "github.com/cosmos/cosmos-sdk/baseapp" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// SimulateMsgCreateUserGroup tests and runs a single MsgCreateUserGroup +func SimulateMsgCreateUserGroup(k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, update, permissions, creator, skip := randomCreateUserGroupFields(r, ctx, accs, k) + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgCreateUserGroup"), nil, nil + } + + // Build the message + msg := types.NewMsgCreateUserGroup( + subspaceID, + update.Name, + update.Description, + permissions, + creator.Address.String(), + ) + + // Send the message + err := simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{creator.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgCreateUserGroup"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgCreateUserGroup", nil), nil, nil + } +} + +// randomCreateUserGroupFields returns the data used to build a random MsgCreateUserGroup +func randomCreateUserGroupFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, +) (subspaceID uint64, update *types.GroupUpdate, permissions types.Permission, account simtypes.Account, skip bool) { + // Get a subspace id + subspaces := k.GetAllSubspaces(ctx) + if len(subspaces) == 0 { + // Skip because there are no subspaces + skip = true + return + } + subspace, _ := RandomSubspace(r, subspaces) + subspaceID = subspace.ID + + // Get a group name + groupName := RandomName(r) + groupDescription := RandomDescription(r) + + // Get a default permission + permissions = RandomPermission(r, []types.Permission{ + types.PermissionWrite, + types.PermissionChangeInfo, + types.PermissionEverything, + }) + + // Get a signer + signers, _ := k.GetUsersWithPermission(ctx, subspace.ID, types.PermissionManageGroups) + acc := GetAccount(RandomAddress(r, signers), accs) + if acc == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + account = *acc + + return subspaceID, types.NewGroupUpdate(groupName, groupDescription), permissions, account, false +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgEditUserGroup tests and runs a single MsgEditUserGroup +func SimulateMsgEditUserGroup(k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, groupID, update, signer, skip := randomEditUserGroupFields(r, ctx, accs, k) + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgEditUserGroup"), nil, nil + } + + // Build the message + msg := types.NewMsgEditUserGroup(subspaceID, groupID, update.Name, update.Description, signer.Address.String()) + + // Send the message + err := simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{signer.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgEditUserGroup"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgEditUserGroup", nil), nil, nil + } +} + +// randomEditUserGroupFields returns the data used to build a random MsgEditUserGroup +func randomEditUserGroupFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, +) (subspaceID uint64, groupID uint32, update *types.GroupUpdate, account simtypes.Account, skip bool) { + // Get a group + groups := k.GetAllUserGroups(ctx) + if len(groups) == 0 { + // Skip if there are no groups + skip = true + return + } + group := RandomGroup(r, groups) + subspaceID = group.SubspaceID + groupID = group.ID + + // Build the update + update = types.NewGroupUpdate(RandomName(r), RandomDescription(r)) + if r.Intn(101) < 50 { + // 50% of chance of not editing the name + update.Name = types.DoNotModify + } + if r.Intn(101) < 50 { + // 50% of chance of not editing the description + update.Description = types.DoNotModify + } + + // Get a signer + signers, _ := k.GetUsersWithPermission(ctx, subspaceID, types.PermissionManageGroups) + acc := GetAccount(RandomAddress(r, signers), accs) + if acc == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + account = *acc + + return subspaceID, groupID, update, account, false +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgSetUserGroupPermissions tests and runs a single MsgSetUserGroupPermissions +func SimulateMsgSetUserGroupPermissions(k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, groupID, permissions, signer, skip := randomSetUserGroupPermissionsFields(r, ctx, accs, k) + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgSetUserGroupPermissions"), nil, nil + } + + // Build the message + msg := types.NewMsgSetUserGroupPermissions(subspaceID, groupID, permissions, signer.Address.String()) + + // Send the message + err := simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{signer.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgSetUserGroupPermissions"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgSetUserGroupPermissions", nil), nil, nil + } +} + +// randomSetUserGroupPermissionsFields returns the data used to build a random MsgSetUserGroupPermissions +func randomSetUserGroupPermissionsFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, +) (subspaceID uint64, groupID uint32, permissions types.Permission, account simtypes.Account, skip bool) { + // Get a subspace id + subspaces := k.GetAllSubspaces(ctx) + if len(subspaces) == 0 { + // Skip because there are no subspaces + skip = true + return + } + subspace, _ := RandomSubspace(r, subspaces) + subspaceID = subspace.ID + + // Get a group + groups := k.GetSubspaceGroups(ctx, subspaceID) + if len(groups) == 0 { + // Skip if there are no groups + skip = true + return + } + groupID = RandomGroup(r, groups).ID + + // Get a permission + permissions = RandomPermission(r, []types.Permission{ + types.PermissionWrite, + types.PermissionModerateContent, + types.PermissionChangeInfo, + types.PermissionManageGroups, + }) + + // Get a signer + signers, _ := k.GetUsersWithPermission(ctx, subspace.ID, types.PermissionSetPermissions) + acc := GetAccount(RandomAddress(r, signers), accs) + if acc == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + account = *acc + + return subspaceID, groupID, permissions, account, false +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgDeleteUserGroup tests and runs a single MsgDeleteUserGroup +func SimulateMsgDeleteUserGroup(k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, groupID, signer, skip := randomDeleteUserGroupFields(r, ctx, accs, k) + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgDeleteUserGroup"), nil, nil + } + + // Build the message + msg := types.NewMsgDeleteUserGroup(subspaceID, groupID, signer.Address.String()) + + // Send the message + err := simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{signer.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgDeleteUserGroup"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgDeleteUserGroup", nil), nil, nil + } +} + +// randomDeleteUserGroupFields returns the data used to build a random MsgDeleteUserGroup +func randomDeleteUserGroupFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, +) (subspaceID uint64, groupID uint32, account simtypes.Account, skip bool) { + // Get a group + groups := k.GetAllUserGroups(ctx) + if len(groups) == 0 { + // Skip if there are no groups + skip = true + return + } + group := RandomGroup(r, groups) + subspaceID = group.SubspaceID + groupID = group.ID + + // Get a signer + signers, _ := k.GetUsersWithPermission(ctx, subspaceID, types.PermissionManageGroups) + acc := GetAccount(RandomAddress(r, signers), accs) + if acc == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + account = *acc + + return subspaceID, groupID, account, false +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgAddUserToUserGroup tests and runs a single MsgAddUserToUserGroup +func SimulateMsgAddUserToUserGroup(k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, groupID, user, signer, skip := randomAddUserToUserGroupFields(r, ctx, accs, k, ak) + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgAddUserToUserGroup"), nil, nil + } + + // Build the message + msg := types.NewMsgAddUserToUserGroup(subspaceID, groupID, user, signer.Address.String()) + + // Send the message + err := simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{signer.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgAddUserToUserGroup"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgAddUserToUserGroup", nil), nil, nil + } +} + +// randomAddUserToUserGroupFields returns the data used to build a random MsgAddUserToUserGroup +func randomAddUserToUserGroupFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, ak authkeeper.AccountKeeper, +) (subspaceID uint64, groupID uint32, user string, account simtypes.Account, skip bool) { + // Get a group + groups := k.GetAllUserGroups(ctx) + if len(groups) == 0 { + // Skip if there are no groups + skip = true + return + } + group := RandomGroup(r, groups) + subspaceID = group.SubspaceID + groupID = group.ID + + // Get a user + accounts := ak.GetAllAccounts(ctx) + userAccount := RandomAuthAccount(r, accounts) + if k.IsMemberOfGroup(ctx, subspaceID, groupID, userAccount.GetAddress()) { + // Skip if the user is already part of group + skip = true + return + } + user = userAccount.GetAddress().String() + + // Get a signer + signers, _ := k.GetUsersWithPermission(ctx, subspaceID, types.PermissionSetPermissions) + acc := GetAccount(RandomAddress(r, signers), accs) + if acc == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + account = *acc + + return subspaceID, groupID, user, account, false +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgRemoveUserFromUserGroup tests and runs a single MsgRemoveUserFromUserGroup +func SimulateMsgRemoveUserFromUserGroup(k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, groupID, user, signer, skip := randomRemoveUserFromUserGroupFields(r, ctx, accs, k) + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgRemoveUserFromUserGroup"), nil, nil + } + + // Build the message + msg := types.NewMsgRemoveUserFromUserGroup(subspaceID, groupID, user, signer.Address.String()) + + // Send the message + err := simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{signer.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgRemoveUserFromUserGroup"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgRemoveUserFromUserGroup", nil), nil, nil + } +} + +// randomRemoveUserFromUserGroupFields returns the data used to build a random MsgRemoveUserFromUserGroup +func randomRemoveUserFromUserGroupFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, +) (subspaceID uint64, groupID uint32, user string, account simtypes.Account, skip bool) { + // Get a group + groups := k.GetAllUserGroups(ctx) + if len(groups) == 0 { + // Skip if there are no groups + skip = true + return + } + group := RandomGroup(r, groups) + subspaceID = group.SubspaceID + groupID = group.ID + + // Get a user + members := k.GetGroupMembers(ctx, subspaceID, groupID) + if len(members) == 0 { + // Skip if there are no member groups to remove + skip = true + return + } + + user = RandomAddress(r, members).String() + + // Get a signer + signers, _ := k.GetUsersWithPermission(ctx, subspaceID, types.PermissionSetPermissions) + acc := GetAccount(RandomAddress(r, signers), accs) + if acc == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + account = *acc + + return subspaceID, groupID, user, account, false +} diff --git a/x/subspaces/simulation/operations_permissions.go b/x/subspaces/simulation/operations_permissions.go new file mode 100644 index 0000000000..e93b98984d --- /dev/null +++ b/x/subspaces/simulation/operations_permissions.go @@ -0,0 +1,87 @@ +package simulation + +// DONTCOVER + +import ( + "math/rand" + + "github.com/desmos-labs/desmos/v2/testutil/simtesting" + + "github.com/cosmos/cosmos-sdk/baseapp" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// SimulateMsgSetUserPermissions tests and runs a single MsgSetUserPermissions +func SimulateMsgSetUserPermissions(k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, user, permissions, creator, skip := randomSetUserPermissionsFields(r, ctx, accs, k) + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgSetUserPermissions"), nil, nil + } + + // Build the message + msg := types.NewMsgSetUserPermissions(subspaceID, user, permissions, creator.Address.String()) + + // Send the message + err := simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{creator.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgSetUserPermissions"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgSetUserPermissions", nil), nil, nil + } +} + +// randomSetUserPermissionsFields returns the data used to build a random MsgSetUserPermissions +func randomSetUserPermissionsFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, +) (subspaceID uint64, target string, permissions types.Permission, account simtypes.Account, skip bool) { + // Get a subspace id + subspaces := k.GetAllSubspaces(ctx) + if len(subspaces) == 0 { + // Skip because there are no subspaces + skip = true + return + } + subspace, _ := RandomSubspace(r, subspaces) + subspaceID = subspace.ID + + // Get a target + users := make([]string, len(accs)) + for i, acc := range accs { + users[i] = acc.Address.String() + } + target = RandomString(r, users) + + // Get a permission + permissions = RandomPermission(r, []types.Permission{ + types.PermissionWrite, + types.PermissionModerateContent, + types.PermissionChangeInfo, + types.PermissionManageGroups, + }) + + // Get a signer + signers, _ := k.GetUsersWithPermission(ctx, subspace.ID, types.PermissionSetPermissions) + acc := GetAccount(RandomAddress(r, signers), accs) + if acc == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + account = *acc + + return subspaceID, target, permissions, account, false +} diff --git a/x/subspaces/simulation/operations_subspaces.go b/x/subspaces/simulation/operations_subspaces.go new file mode 100644 index 0000000000..5bc0eb988e --- /dev/null +++ b/x/subspaces/simulation/operations_subspaces.go @@ -0,0 +1,223 @@ +package simulation + +// DONTCOVER + +import ( + "math/rand" + + "github.com/desmos-labs/desmos/v2/testutil/simtesting" + + "github.com/cosmos/cosmos-sdk/baseapp" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + + "github.com/desmos-labs/desmos/v2/x/subspaces/keeper" + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// SimulateMsgCreateSubspace tests and runs a single MsgCreateSubspace +func SimulateMsgCreateSubspace(ak authkeeper.AccountKeeper, bk bankkeeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspace, creator, skip, err := randomSubspaceCreateFields(r, accs) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgCreateSubspace"), nil, err + } + + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgCreateSubspace"), nil, nil + } + + // Build the message + msg := types.NewMsgCreateSubspace( + subspace.Name, + subspace.Description, + subspace.Treasury, + subspace.Owner, + subspace.Creator, + ) + + // Send the message + err = simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{creator.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgCreateSubspace"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgCreateSubspace", nil), nil, nil + } +} + +// randomSubspaceCreateFields returns the data used to build a random MsgCreateSubspace +func randomSubspaceCreateFields( + r *rand.Rand, accs []simtypes.Account, +) (subspace types.Subspace, creator simtypes.Account, skip bool, err error) { + // Get the subspace data + subspace = GenerateRandomSubspace(r, accs) + + // Get the creator + sdkAddr, err := sdk.AccAddressFromBech32(subspace.Creator) + if err != nil { + return + } + account := GetAccount(sdkAddr, accs) + if account == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + creator = *account + + return +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgEditSubspace tests and runs a single msg edit subspace +func SimulateMsgEditSubspace( + k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, update, editor, skip := randomEditSubspaceFields(r, ctx, accs, k) + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgEditSubspace"), nil, nil + } + + // Build the message + msg := types.NewMsgEditSubspace( + subspaceID, + update.Name, + update.Description, + update.Treasury, + update.Owner, + editor.Address.String(), + ) + + // Send the data + err := simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{editor.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgEditSubspace"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgEditSubspace", nil), nil, nil + } +} + +// randomEditSubspaceFields returns the data needed to edit a subspace +func randomEditSubspaceFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, +) (subspaceID uint64, update *types.SubspaceUpdate, account simtypes.Account, skip bool) { + // Get a subspace id + subspaces := k.GetAllSubspaces(ctx) + if len(subspaces) == 0 { + // Skip because there are no subspaces + skip = true + return + } + subspace, _ := RandomSubspace(r, subspaces) + subspaceID = subspace.ID + + // Get an editor + editors, _ := k.GetUsersWithPermission(ctx, subspace.ID, types.PermissionChangeInfo) + acc := GetAccount(RandomAddress(r, editors), accs) + if acc == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + account = *acc + + // Build the update data + update = types.NewSubspaceUpdate( + RandomName(r), + RandomDescription(r), + account.Address.String(), + account.Address.String(), + ) + if r.Intn(101) < 50 { + // 50% of chance of not editing the name + update.Name = types.DoNotModify + } + if r.Intn(101) < 50 { + // 50% of chance of not editing the description + update.Description = types.DoNotModify + } + if r.Intn(101) < 50 { + // 50% of chance of not editing the treasury + update.Treasury = types.DoNotModify + } + if r.Intn(101) < 50 { + // 50% of chance of not editing the owner + update.Owner = types.DoNotModify + } + + return subspaceID, update, account, false +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgDeleteSubspace tests and runs a single msg delete subspace +func SimulateMsgDeleteSubspace( + k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, editor, skip := randomDeleteSubspaceFields(r, ctx, accs, k) + if skip { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgDeleteSubspace"), nil, nil + } + + // Build the message + msg := types.NewMsgDeleteSubspace(subspaceID, editor.Address.String()) + + // Send the data + err := simtesting.SendMsg(r, app, ak, bk, msg, ctx, chainID, DefaultGasValue, []cryptotypes.PrivKey{editor.PrivKey}) + if err != nil { + return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "MsgDeleteSubspace"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "MsgDeleteSubspace", nil), nil, nil + } +} + +// randomDeleteSubspaceFields returns the data needed to delete a subspace +func randomDeleteSubspaceFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, +) (subspaceID uint64, account simtypes.Account, skip bool) { + // Get a subspace id + subspaces := k.GetAllSubspaces(ctx) + if len(subspaces) == 0 { + // Skip because there are no subspaces + skip = true + return + } + subspace, _ := RandomSubspace(r, subspaces) + subspaceID = subspace.ID + + // Get an editor + editors, _ := k.GetUsersWithPermission(ctx, subspace.ID, types.PermissionDeleteSubspace) + acc := GetAccount(RandomAddress(r, editors), accs) + if acc == nil { + // Skip the operation without error as the account is not valid + skip = true + return + } + account = *acc + + return subspaceID, account, false +} diff --git a/x/subspaces/simulation/utils.go b/x/subspaces/simulation/utils.go new file mode 100644 index 0000000000..898b34a794 --- /dev/null +++ b/x/subspaces/simulation/utils.go @@ -0,0 +1,107 @@ +package simulation + +// DONTCOVER + +import ( + "math/rand" + "time" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +// RandomGenesisSubspace picks a random genesis subspace from the given slice +func RandomGenesisSubspace(r *rand.Rand, subspaces []types.GenesisSubspace) types.GenesisSubspace { + return subspaces[r.Intn(len(subspaces))] +} + +// RandomSubspace picks a random subspace from an array and returns its position as well as value. +func RandomSubspace(r *rand.Rand, subspaces []types.Subspace) (types.Subspace, int) { + idx := r.Intn(len(subspaces)) + return subspaces[idx], idx +} + +// GenerateRandomSubspace generates a new subspace containing random data +func GenerateRandomSubspace(r *rand.Rand, accs []simtypes.Account) types.Subspace { + simAccount, _ := simtypes.RandomAcc(r, accs) + creator := simAccount.Address.String() + + return types.NewSubspace( + RandomID(r), + RandomName(r), + RandomDescription(r), + creator, + creator, + creator, + RandomDate(r), + ) +} + +// RandomID returns a new random ID +func RandomID(r *rand.Rand) uint64 { + return r.Uint64() +} + +// RandomName returns a random subspace name +func RandomName(r *rand.Rand) string { + return simtypes.RandStringOfLength(r, 10) +} + +// RandomDescription returns a random subspace description +func RandomDescription(r *rand.Rand) string { + return simtypes.RandStringOfLength(r, 30) +} + +// RandomDate returns a random post creation date +func RandomDate(r *rand.Rand) time.Time { + min := time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC).Unix() + max := time.Date(2010, 1, 0, 0, 0, 0, 0, time.UTC).Unix() + delta := max - min + + sec := r.Int63n(delta) + min + return time.Unix(sec, 0).Truncate(time.Millisecond) +} + +// RandomString returns a random string from the given slice +func RandomString(r *rand.Rand, strings []string) string { + return strings[r.Intn(len(strings))] +} + +// RandomGroup returns a random group selecting it from the list of groups given +func RandomGroup(r *rand.Rand, groups []types.UserGroup) types.UserGroup { + return groups[r.Intn(len(groups))] +} + +// RandomPermission returns a random permission from the given slice +func RandomPermission(r *rand.Rand, permissions []types.Permission) types.Permission { + return permissions[r.Intn(len(permissions))] +} + +// RandomAccount returns a random account from the slice given +func RandomAccount(r *rand.Rand, accounts []simtypes.Account) simtypes.Account { + return accounts[r.Intn(len(accounts))] +} + +// RandomAddress returns a random address from the slice given +func RandomAddress(r *rand.Rand, addresses []sdk.AccAddress) sdk.AccAddress { + return addresses[r.Intn(len(addresses))] +} + +// RandomAuthAccount returns a random account from the slice given +func RandomAuthAccount(r *rand.Rand, accounts []authtypes.AccountI) authtypes.AccountI { + return accounts[r.Intn(len(accounts))] +} + +// GetAccount gets the account having the given address from the accs list +func GetAccount(address sdk.Address, accs []simtypes.Account) *simtypes.Account { + for _, acc := range accs { + if acc.Address.Equals(address) { + return &acc + } + } + return nil +} diff --git a/x/subspaces/types/codec.go b/x/subspaces/types/codec.go new file mode 100644 index 0000000000..8807c40ffa --- /dev/null +++ b/x/subspaces/types/codec.go @@ -0,0 +1,48 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(MsgCreateSubspace{}, "desmos/MsgCreateSubspace", nil) + cdc.RegisterConcrete(MsgEditSubspace{}, "desmos/MsgEditSubspace", nil) + cdc.RegisterConcrete(MsgCreateUserGroup{}, "desmos/MsgCreateUserGroup", nil) + cdc.RegisterConcrete(MsgEditUserGroup{}, "desmos/MsgEditUserGroup", nil) + cdc.RegisterConcrete(MsgSetUserGroupPermissions{}, "desmos/MsgSetUserGroupPermissions", nil) + cdc.RegisterConcrete(MsgDeleteUserGroup{}, "desmos/MsgDeleteUserGroup", nil) + cdc.RegisterConcrete(MsgAddUserToUserGroup{}, "desmos/MsgAddUserToUserGroup", nil) + cdc.RegisterConcrete(MsgRemoveUserFromUserGroup{}, "desmos/MsgRemoveUserFromUserGroup", nil) + cdc.RegisterConcrete(MsgSetUserPermissions{}, "desmos/MsgSetUserPermissions", nil) +} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgCreateSubspace{}, + &MsgEditSubspace{}, + &MsgCreateUserGroup{}, + &MsgEditUserGroup{}, + &MsgSetUserGroupPermissions{}, + &MsgDeleteUserGroup{}, + &MsgAddUserToUserGroup{}, + &MsgRemoveUserFromUserGroup{}, + &MsgSetUserPermissions{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +var ( + amino = codec.NewLegacyAmino() + + // AminoCodec references the global x/subspaces module codec. Note, the codec should + // ONLY be used in certain instances of tests and for JSON encoding as Amino is + // still used for that purpose. + // + // The actual codec used for serialization should be provided to x/subspaces and + // defined at the application level. + AminoCodec = codec.NewAminoCodec(amino) +) diff --git a/x/subspaces/types/errors.go b/x/subspaces/types/errors.go new file mode 100644 index 0000000000..3b5714886e --- /dev/null +++ b/x/subspaces/types/errors.go @@ -0,0 +1,11 @@ +package types + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var ( + // ErrPermissionDenied is returned if a user cannot perform a specific action inside a subspace + ErrPermissionDenied = sdkerrors.Register(ModuleName, 1, "permission denied for user") + ErrInvalidGenesis = sdkerrors.Register(ModuleName, 2, "invalid genesis state") +) diff --git a/x/subspaces/types/events.go b/x/subspaces/types/events.go new file mode 100644 index 0000000000..cb0df1d9cd --- /dev/null +++ b/x/subspaces/types/events.go @@ -0,0 +1,23 @@ +package types + +// Subspaces module event types +const ( + EventTypeCreateSubspace = "create_subspace" + EventTypeEditSubspace = "edit_subspace" + EventTypeDeleteSubspace = "delete_subspace" + EventTypeCreateUserGroup = "create_user_group" + EventTypeEditUserGroup = "edit_user_group" + EventTypeSetUserGroupPermissions = "set_user_group_permissions" + EventTypeDeleteUserGroup = "delete_user_group" + EventTypeAddUserToGroup = "add_group_member" + EventTypeRemoveUserFromGroup = "remove_group_member" + EventTypeSetUserPermissions = "set_user_permissions" + + AttributeValueCategory = ModuleName + AttributeKeySubspaceID = "subspace_id" + AttributeKeySubspaceName = "subspace_name" + AttributeKeySubspaceCreator = "subspace_creator" + AttributeKeyCreationTime = "creation_date" + AttributeKeyUserGroupID = "user_group_id" + AttributeKeyUser = "user" +) diff --git a/x/subspaces/types/genesis.go b/x/subspaces/types/genesis.go new file mode 100644 index 0000000000..d2ba4f20ac --- /dev/null +++ b/x/subspaces/types/genesis.go @@ -0,0 +1,258 @@ +package types + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// NewGenesisSubspace returns a new GenesisSubspace instance +func NewGenesisSubspace(subspace Subspace, initialGroupID uint32) GenesisSubspace { + return GenesisSubspace{ + Subspace: subspace, + InitialGroupID: initialGroupID, + } +} + +// Validate returns an error if something is wrong within the subspace data +func (subspace GenesisSubspace) Validate() error { + if subspace.InitialGroupID == 0 { + return fmt.Errorf("invalid initial group id: %d", subspace.InitialGroupID) + } + + return subspace.Subspace.Validate() +} + +// ------------------------------------------------------------------------------------------------------------------- + +// NewACLEntry returns a new ACLEntry instance +func NewACLEntry(subspaceID uint64, user string, permissions Permission) ACLEntry { + return ACLEntry{ + SubspaceID: subspaceID, + User: user, + Permissions: permissions, + } +} + +// Validate returns an error if something is wrong within the entry data +func (entry ACLEntry) Validate() error { + if entry.SubspaceID == 0 { + return fmt.Errorf("invalid subspace id: %d", entry.SubspaceID) + } + + _, err := sdk.AccAddressFromBech32(entry.User) + if err != nil { + return fmt.Errorf("invalid user address: %s", entry.User) + } + + return nil +} + +// ------------------------------------------------------------------------------------------------------------------- + +// NewUserGroupMembersEntry returns a new UserGroupMembersEntry instance +func NewUserGroupMembersEntry(subspaceID uint64, groupID uint32, members []string) UserGroupMembersEntry { + return UserGroupMembersEntry{ + SubspaceID: subspaceID, + GroupID: groupID, + Members: members, + } +} + +// Validate returns an error if something is wrong within the entry data +func (entry UserGroupMembersEntry) Validate() error { + if entry.SubspaceID == 0 { + return fmt.Errorf("invalid subspace id: %d", entry.SubspaceID) + } + + if entry.GroupID == 0 { + return fmt.Errorf("invalid group id: %d", entry.GroupID) + } + + for _, user := range entry.Members { + _, err := sdk.AccAddressFromBech32(user) + if err != nil { + return fmt.Errorf("invalid user address: %s", user) + } + } + + return nil +} + +// ------------------------------------------------------------------------------------------------------------------- + +// NewGenesisState creates a new genesis state +func NewGenesisState( + initialSubspaceID uint64, subspaces []GenesisSubspace, acl []ACLEntry, + userGroups []UserGroup, userGroupMembers []UserGroupMembersEntry, +) *GenesisState { + return &GenesisState{ + InitialSubspaceID: initialSubspaceID, + Subspaces: subspaces, + ACL: acl, + UserGroups: userGroups, + UserGroupsMembers: userGroupMembers, + } +} + +// DefaultGenesisState returns a default GenesisState +func DefaultGenesisState() *GenesisState { + return NewGenesisState(1, nil, nil, nil, nil) +} + +// ------------------------------------------------------------------------------------------------------------------- + +// ValidateGenesis validates the given genesis state and returns an error if something is invalid +func ValidateGenesis(data *GenesisState) error { + // Make sure the initial subspace id is valid + if data.InitialSubspaceID <= uint64(len(data.Subspaces)) { + return fmt.Errorf("invalid initial subspace id: %d", data.InitialSubspaceID) + } + + // Validate the subspace + for _, subspace := range data.Subspaces { + err := subspace.Validate() + if err != nil { + return err + } + + if containsDuplicatedSubspace(data.Subspaces, subspace) { + return fmt.Errorf("duplicated subspace: %d", subspace.Subspace.ID) + } + } + + // Validate the ACL entries + for _, entry := range data.ACL { + err := entry.Validate() + if err != nil { + return err + } + + if containsDuplicatedACLEntry(data.ACL, entry) { + return fmt.Errorf("duplicated ACL entry for subspace %d and user %s", entry.SubspaceID, entry.User) + } + + // Make sure the associated subspace exists + subspace, found := findSubspace(data.Subspaces, entry.SubspaceID) + if !found { + return fmt.Errorf("invalid ACL entry: subspace %d not found", subspace.Subspace.ID) + } + } + + // Validate the user groups + groupsCount := map[uint64]int{} + for _, group := range data.UserGroups { + err := group.Validate() + if err != nil { + return err + } + + if containsDuplicatedGroups(data.UserGroups, group) { + return fmt.Errorf("duplicated group for subspace %d and group %d", group.SubspaceID, group.ID) + } + + // Increment the groups count for this subspace + groupsCount[group.SubspaceID]++ + } + + // Make sure each subspace has a correct initial group id based on the number of groups inside that subspace + for subspaceID, count := range groupsCount { + genSub, found := findSubspace(data.Subspaces, subspaceID) + if !found { + return fmt.Errorf("invalid group id: subspace %d not found", subspaceID) + } + + if genSub.InitialGroupID <= uint32(count) { + return fmt.Errorf("invalid initial group id for subspace %d: %d", genSub.Subspace.ID, genSub.InitialGroupID) + } + } + + // Validate the group members + for _, entry := range data.UserGroupsMembers { + err := entry.Validate() + if err != nil { + return err + } + + if containsDuplicatedMembersEntries(data.UserGroupsMembers, entry) { + return fmt.Errorf("duplicated user group members entry for group %d within subspace %d", entry.GroupID, entry.SubspaceID) + } + + // Make sure the associated subspace exists + _, found := findGroup(data.UserGroups, entry.SubspaceID, entry.GroupID) + if !found { + return fmt.Errorf("invalid group members entry: group %d for subspace %d not found", + entry.GroupID, entry.SubspaceID) + } + } + + return nil +} + +// findSubspace searches the subspace with the given id inside the provided slice +func findSubspace(subspaces []GenesisSubspace, subspaceID uint64) (genSub GenesisSubspace, found bool) { + for _, subspace := range subspaces { + if subspace.Subspace.ID == subspaceID { + return subspace, true + } + } + return GenesisSubspace{}, false +} + +// findGroup searches the group for the group having the given id and subspace id inside the given slice +func findGroup(groups []UserGroup, subspaceID uint64, groupID uint32) (group UserGroup, found bool) { + for _, group := range groups { + if group.SubspaceID == subspaceID && group.ID == groupID { + return group, true + } + } + return UserGroup{}, false +} + +// containsDuplicatedSubspace tells whether the given subspaces slice contains two or more +// subspaces with the same id of the given subspace +func containsDuplicatedSubspace(subspaces []GenesisSubspace, subspace GenesisSubspace) bool { + var count = 0 + for _, s := range subspaces { + if s.Subspace.ID == subspace.Subspace.ID { + count++ + } + } + return count > 1 +} + +// containsDuplicatedACLEntry tells whether the given entries slice contains two or more +// entries for the same user and subspace +func containsDuplicatedACLEntry(entries []ACLEntry, entry ACLEntry) bool { + var count = 0 + for _, e := range entries { + if e.SubspaceID == entry.SubspaceID && e.User == entry.User { + count++ + } + } + return count > 1 +} + +// containsDuplicatedGroups tells whether the given groups slice contains two or more +// groups for the same subspace having the same name +func containsDuplicatedGroups(groups []UserGroup, group UserGroup) bool { + var count = 0 + for _, g := range groups { + if g.SubspaceID == group.SubspaceID && g.ID == group.ID { + count++ + } + } + return count > 1 +} + +// containsDuplicatedMembersEntries tells whether the given entries slice contains two or more +// entries for the same subspace and group id +func containsDuplicatedMembersEntries(entries []UserGroupMembersEntry, entry UserGroupMembersEntry) bool { + var count = 0 + for _, e := range entries { + if e.SubspaceID == entry.SubspaceID && e.GroupID == entry.GroupID { + count++ + } + } + return count > 1 +} diff --git a/x/subspaces/types/genesis.pb.go b/x/subspaces/types/genesis.pb.go new file mode 100644 index 0000000000..9d4aeb2357 --- /dev/null +++ b/x/subspaces/types/genesis.pb.go @@ -0,0 +1,1413 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/subspaces/v1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState contains the data of the genesis state for the subspaces module +type GenesisState struct { + InitialSubspaceID uint64 `protobuf:"varint,1,opt,name=initial_subspace_id,json=initialSubspaceId,proto3" json:"initial_subspace_id,omitempty"` + Subspaces []GenesisSubspace `protobuf:"bytes,2,rep,name=subspaces,proto3" json:"subspaces"` + ACL []ACLEntry `protobuf:"bytes,3,rep,name=acl,proto3" json:"acl"` + UserGroups []UserGroup `protobuf:"bytes,4,rep,name=user_groups,json=userGroups,proto3" json:"user_groups"` + UserGroupsMembers []UserGroupMembersEntry `protobuf:"bytes,5,rep,name=user_groups_members,json=userGroupsMembers,proto3" json:"user_groups_members"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_bce8af665337782b, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetInitialSubspaceID() uint64 { + if m != nil { + return m.InitialSubspaceID + } + return 0 +} + +func (m *GenesisState) GetSubspaces() []GenesisSubspace { + if m != nil { + return m.Subspaces + } + return nil +} + +func (m *GenesisState) GetACL() []ACLEntry { + if m != nil { + return m.ACL + } + return nil +} + +func (m *GenesisState) GetUserGroups() []UserGroup { + if m != nil { + return m.UserGroups + } + return nil +} + +func (m *GenesisState) GetUserGroupsMembers() []UserGroupMembersEntry { + if m != nil { + return m.UserGroupsMembers + } + return nil +} + +// GenesisSubspace contains the genesis data for a single subspace +type GenesisSubspace struct { + Subspace Subspace `protobuf:"bytes,1,opt,name=subspace,proto3" json:"subspace"` + InitialGroupID uint32 `protobuf:"varint,2,opt,name=initial_group_id,json=initialGroupId,proto3" json:"initial_group_id,omitempty"` +} + +func (m *GenesisSubspace) Reset() { *m = GenesisSubspace{} } +func (m *GenesisSubspace) String() string { return proto.CompactTextString(m) } +func (*GenesisSubspace) ProtoMessage() {} +func (*GenesisSubspace) Descriptor() ([]byte, []int) { + return fileDescriptor_bce8af665337782b, []int{1} +} +func (m *GenesisSubspace) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisSubspace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisSubspace.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisSubspace) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisSubspace.Merge(m, src) +} +func (m *GenesisSubspace) XXX_Size() int { + return m.Size() +} +func (m *GenesisSubspace) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisSubspace.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisSubspace proto.InternalMessageInfo + +func (m *GenesisSubspace) GetSubspace() Subspace { + if m != nil { + return m.Subspace + } + return Subspace{} +} + +func (m *GenesisSubspace) GetInitialGroupID() uint32 { + if m != nil { + return m.InitialGroupID + } + return 0 +} + +// ACLEntry represents a single Access Control List entry +type ACLEntry struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty"` + User string `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"` + Permissions uint32 `protobuf:"varint,3,opt,name=permissions,proto3" json:"permissions,omitempty"` +} + +func (m *ACLEntry) Reset() { *m = ACLEntry{} } +func (m *ACLEntry) String() string { return proto.CompactTextString(m) } +func (*ACLEntry) ProtoMessage() {} +func (*ACLEntry) Descriptor() ([]byte, []int) { + return fileDescriptor_bce8af665337782b, []int{2} +} +func (m *ACLEntry) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ACLEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ACLEntry.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ACLEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_ACLEntry.Merge(m, src) +} +func (m *ACLEntry) XXX_Size() int { + return m.Size() +} +func (m *ACLEntry) XXX_DiscardUnknown() { + xxx_messageInfo_ACLEntry.DiscardUnknown(m) +} + +var xxx_messageInfo_ACLEntry proto.InternalMessageInfo + +func (m *ACLEntry) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *ACLEntry) GetUser() string { + if m != nil { + return m.User + } + return "" +} + +func (m *ACLEntry) GetPermissions() uint32 { + if m != nil { + return m.Permissions + } + return 0 +} + +// UserGroupMembersEntry contains all the members of a specific user group +type UserGroupMembersEntry struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty"` + GroupID uint32 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + Members []string `protobuf:"bytes,3,rep,name=members,proto3" json:"members,omitempty"` +} + +func (m *UserGroupMembersEntry) Reset() { *m = UserGroupMembersEntry{} } +func (m *UserGroupMembersEntry) String() string { return proto.CompactTextString(m) } +func (*UserGroupMembersEntry) ProtoMessage() {} +func (*UserGroupMembersEntry) Descriptor() ([]byte, []int) { + return fileDescriptor_bce8af665337782b, []int{3} +} +func (m *UserGroupMembersEntry) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UserGroupMembersEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UserGroupMembersEntry.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *UserGroupMembersEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_UserGroupMembersEntry.Merge(m, src) +} +func (m *UserGroupMembersEntry) XXX_Size() int { + return m.Size() +} +func (m *UserGroupMembersEntry) XXX_DiscardUnknown() { + xxx_messageInfo_UserGroupMembersEntry.DiscardUnknown(m) +} + +var xxx_messageInfo_UserGroupMembersEntry proto.InternalMessageInfo + +func (m *UserGroupMembersEntry) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *UserGroupMembersEntry) GetGroupID() uint32 { + if m != nil { + return m.GroupID + } + return 0 +} + +func (m *UserGroupMembersEntry) GetMembers() []string { + if m != nil { + return m.Members + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "desmos.subspaces.v1.GenesisState") + proto.RegisterType((*GenesisSubspace)(nil), "desmos.subspaces.v1.GenesisSubspace") + proto.RegisterType((*ACLEntry)(nil), "desmos.subspaces.v1.ACLEntry") + proto.RegisterType((*UserGroupMembersEntry)(nil), "desmos.subspaces.v1.UserGroupMembersEntry") +} + +func init() { proto.RegisterFile("desmos/subspaces/v1/genesis.proto", fileDescriptor_bce8af665337782b) } + +var fileDescriptor_bce8af665337782b = []byte{ + // 513 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0xcf, 0x8b, 0xd3, 0x40, + 0x14, 0xc7, 0x3b, 0x9b, 0x6a, 0xdb, 0x17, 0xad, 0x76, 0xea, 0x42, 0x58, 0x30, 0xa9, 0x8b, 0x48, + 0x11, 0x4c, 0xd8, 0x7a, 0x93, 0x05, 0xd9, 0xec, 0x96, 0xb5, 0x50, 0x2f, 0x59, 0xbc, 0x78, 0xa9, + 0x49, 0x33, 0xc4, 0x81, 0xa6, 0x09, 0x99, 0xa4, 0xb8, 0xf8, 0x4f, 0xec, 0xc1, 0x83, 0x78, 0xda, + 0x3f, 0x67, 0x8f, 0x7b, 0xf4, 0x14, 0x24, 0xbd, 0xf8, 0x67, 0x48, 0x26, 0x99, 0x36, 0xd4, 0x28, + 0xec, 0x6d, 0xe6, 0xfd, 0xf8, 0xbc, 0xef, 0xbc, 0xf7, 0x06, 0x9e, 0xb9, 0x84, 0xf9, 0x01, 0x33, + 0x58, 0xe2, 0xb0, 0xd0, 0x9e, 0x13, 0x66, 0xac, 0x8e, 0x0c, 0x8f, 0x2c, 0x09, 0xa3, 0x4c, 0x0f, + 0xa3, 0x20, 0x0e, 0x70, 0xbf, 0x08, 0xd1, 0x37, 0x21, 0xfa, 0xea, 0xe8, 0xe0, 0x89, 0x17, 0x78, + 0x01, 0xf7, 0x1b, 0xf9, 0xa9, 0x08, 0x3d, 0x18, 0xd4, 0xd1, 0xfc, 0xc0, 0x25, 0x8b, 0x12, 0x76, + 0x78, 0x25, 0xc1, 0x83, 0xf3, 0x02, 0x7f, 0x11, 0xdb, 0x31, 0xc1, 0x63, 0xe8, 0xd3, 0x25, 0x8d, + 0xa9, 0xbd, 0x98, 0x89, 0xac, 0x19, 0x75, 0x15, 0x34, 0x40, 0xc3, 0xa6, 0xb9, 0x9f, 0xa5, 0x5a, + 0x6f, 0x52, 0xb8, 0x2f, 0x4a, 0xef, 0xe4, 0xcc, 0xea, 0xd1, 0x1d, 0x93, 0x8b, 0xdf, 0x41, 0x67, + 0x53, 0x54, 0xd9, 0x1b, 0x48, 0x43, 0x79, 0xf4, 0x5c, 0xaf, 0x11, 0xae, 0x8b, 0xe2, 0xa5, 0xcd, + 0x6c, 0xde, 0xa4, 0x5a, 0xc3, 0xda, 0x26, 0xe3, 0x63, 0x90, 0xec, 0xf9, 0x42, 0x91, 0x38, 0xe3, + 0x69, 0x2d, 0xe3, 0xe4, 0x74, 0x3a, 0x5e, 0xc6, 0xd1, 0xa5, 0x29, 0xe7, 0xc9, 0x59, 0xaa, 0x49, + 0x27, 0xa7, 0x53, 0x2b, 0x4f, 0xc3, 0x63, 0x90, 0x13, 0x46, 0xa2, 0x99, 0x17, 0x05, 0x49, 0xc8, + 0x94, 0x26, 0xa7, 0xa8, 0xb5, 0x94, 0x0f, 0x8c, 0x44, 0xe7, 0x79, 0x58, 0xa9, 0x01, 0x12, 0x61, + 0x60, 0xf8, 0x13, 0xf4, 0x2b, 0x98, 0x99, 0x4f, 0x7c, 0x87, 0x44, 0x4c, 0xb9, 0xc7, 0x71, 0x2f, + 0xff, 0x8f, 0x7b, 0x5f, 0x04, 0x17, 0x0a, 0x0b, 0x74, 0x6f, 0x8b, 0x2e, 0xbd, 0x6f, 0xda, 0xdf, + 0xaf, 0x35, 0xf4, 0xfb, 0x5a, 0x43, 0x87, 0x3f, 0x10, 0x3c, 0xda, 0xe9, 0x0a, 0x7e, 0x0b, 0x6d, + 0x01, 0xe7, 0xa3, 0xf8, 0x57, 0x27, 0x76, 0xda, 0xb8, 0x49, 0xc2, 0xc7, 0xf0, 0x58, 0x8c, 0x95, + 0xbf, 0x21, 0x9f, 0xe9, 0xde, 0x00, 0x0d, 0x1f, 0x9a, 0x38, 0x4b, 0xb5, 0x6e, 0x39, 0x53, 0x2e, + 0x69, 0x72, 0x66, 0x75, 0x69, 0xf5, 0xee, 0x56, 0xc4, 0x7d, 0x85, 0xb6, 0xe8, 0x36, 0x36, 0x40, + 0xfe, 0x7b, 0x45, 0xba, 0x59, 0xaa, 0x41, 0x65, 0x37, 0x80, 0x6d, 0x97, 0x02, 0x43, 0x33, 0x7f, + 0x38, 0x2f, 0xdc, 0xb1, 0xf8, 0x19, 0x0f, 0x40, 0x0e, 0x49, 0xe4, 0x53, 0xc6, 0x68, 0xb0, 0x64, + 0x8a, 0x94, 0x6b, 0xb2, 0xaa, 0xa6, 0x4a, 0xf1, 0x6f, 0x08, 0xf6, 0x6b, 0xdb, 0x7a, 0x77, 0x29, + 0x2f, 0xa0, 0xbd, 0xd3, 0x07, 0x39, 0x4b, 0xb5, 0x96, 0x68, 0x40, 0xcb, 0x2b, 0x5e, 0x8e, 0x15, + 0x68, 0x89, 0x61, 0xe7, 0x1b, 0xd8, 0xb1, 0xc4, 0x75, 0x2b, 0xcb, 0x9c, 0xde, 0x64, 0x2a, 0xba, + 0xcd, 0x54, 0xf4, 0x2b, 0x53, 0xd1, 0xd5, 0x5a, 0x6d, 0xdc, 0xae, 0xd5, 0xc6, 0xcf, 0xb5, 0xda, + 0xf8, 0x38, 0xf2, 0x68, 0xfc, 0x39, 0x71, 0xf4, 0x79, 0xe0, 0x1b, 0xc5, 0xb8, 0x5e, 0x2d, 0x6c, + 0x87, 0x95, 0x67, 0x63, 0x35, 0x32, 0xbe, 0x54, 0xfe, 0x66, 0x7c, 0x19, 0x12, 0xe6, 0xdc, 0xe7, + 0x1f, 0xf3, 0xf5, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x21, 0xfd, 0x5d, 0x3a, 0x0a, 0x04, 0x00, + 0x00, +} + +func (this *GenesisState) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*GenesisState) + if !ok { + that2, ok := that.(GenesisState) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.InitialSubspaceID != that1.InitialSubspaceID { + return false + } + if len(this.Subspaces) != len(that1.Subspaces) { + return false + } + for i := range this.Subspaces { + if !this.Subspaces[i].Equal(&that1.Subspaces[i]) { + return false + } + } + if len(this.ACL) != len(that1.ACL) { + return false + } + for i := range this.ACL { + if !this.ACL[i].Equal(&that1.ACL[i]) { + return false + } + } + if len(this.UserGroups) != len(that1.UserGroups) { + return false + } + for i := range this.UserGroups { + if !this.UserGroups[i].Equal(&that1.UserGroups[i]) { + return false + } + } + if len(this.UserGroupsMembers) != len(that1.UserGroupsMembers) { + return false + } + for i := range this.UserGroupsMembers { + if !this.UserGroupsMembers[i].Equal(&that1.UserGroupsMembers[i]) { + return false + } + } + return true +} +func (this *GenesisSubspace) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*GenesisSubspace) + if !ok { + that2, ok := that.(GenesisSubspace) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Subspace.Equal(&that1.Subspace) { + return false + } + if this.InitialGroupID != that1.InitialGroupID { + return false + } + return true +} +func (this *ACLEntry) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ACLEntry) + if !ok { + that2, ok := that.(ACLEntry) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.SubspaceID != that1.SubspaceID { + return false + } + if this.User != that1.User { + return false + } + if this.Permissions != that1.Permissions { + return false + } + return true +} +func (this *UserGroupMembersEntry) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*UserGroupMembersEntry) + if !ok { + that2, ok := that.(UserGroupMembersEntry) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.SubspaceID != that1.SubspaceID { + return false + } + if this.GroupID != that1.GroupID { + return false + } + if len(this.Members) != len(that1.Members) { + return false + } + for i := range this.Members { + if this.Members[i] != that1.Members[i] { + return false + } + } + return true +} +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.UserGroupsMembers) > 0 { + for iNdEx := len(m.UserGroupsMembers) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.UserGroupsMembers[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if len(m.UserGroups) > 0 { + for iNdEx := len(m.UserGroups) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.UserGroups[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.ACL) > 0 { + for iNdEx := len(m.ACL) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ACL[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.Subspaces) > 0 { + for iNdEx := len(m.Subspaces) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Subspaces[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.InitialSubspaceID != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.InitialSubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *GenesisSubspace) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisSubspace) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisSubspace) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.InitialGroupID != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.InitialGroupID)) + i-- + dAtA[i] = 0x10 + } + { + size, err := m.Subspace.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ACLEntry) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ACLEntry) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ACLEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Permissions != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Permissions)) + i-- + dAtA[i] = 0x18 + } + if len(m.User) > 0 { + i -= len(m.User) + copy(dAtA[i:], m.User) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.User))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceID != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *UserGroupMembersEntry) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UserGroupMembersEntry) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UserGroupMembersEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Members) > 0 { + for iNdEx := len(m.Members) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Members[iNdEx]) + copy(dAtA[i:], m.Members[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Members[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if m.GroupID != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.GroupID)) + i-- + dAtA[i] = 0x10 + } + if m.SubspaceID != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.InitialSubspaceID != 0 { + n += 1 + sovGenesis(uint64(m.InitialSubspaceID)) + } + if len(m.Subspaces) > 0 { + for _, e := range m.Subspaces { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.ACL) > 0 { + for _, e := range m.ACL { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.UserGroups) > 0 { + for _, e := range m.UserGroups { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.UserGroupsMembers) > 0 { + for _, e := range m.UserGroupsMembers { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *GenesisSubspace) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Subspace.Size() + n += 1 + l + sovGenesis(uint64(l)) + if m.InitialGroupID != 0 { + n += 1 + sovGenesis(uint64(m.InitialGroupID)) + } + return n +} + +func (m *ACLEntry) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovGenesis(uint64(m.SubspaceID)) + } + l = len(m.User) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if m.Permissions != 0 { + n += 1 + sovGenesis(uint64(m.Permissions)) + } + return n +} + +func (m *UserGroupMembersEntry) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovGenesis(uint64(m.SubspaceID)) + } + if m.GroupID != 0 { + n += 1 + sovGenesis(uint64(m.GroupID)) + } + if len(m.Members) > 0 { + for _, s := range m.Members { + l = len(s) + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialSubspaceID", wireType) + } + m.InitialSubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitialSubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subspaces", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Subspaces = append(m.Subspaces, GenesisSubspace{}) + if err := m.Subspaces[len(m.Subspaces)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ACL", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ACL = append(m.ACL, ACLEntry{}) + if err := m.ACL[len(m.ACL)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UserGroups", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UserGroups = append(m.UserGroups, UserGroup{}) + if err := m.UserGroups[len(m.UserGroups)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UserGroupsMembers", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UserGroupsMembers = append(m.UserGroupsMembers, UserGroupMembersEntry{}) + if err := m.UserGroupsMembers[len(m.UserGroupsMembers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenesisSubspace) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisSubspace: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisSubspace: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Subspace.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialGroupID", wireType) + } + m.InitialGroupID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitialGroupID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ACLEntry) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ACLEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ACLEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.User = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) + } + m.Permissions = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Permissions |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *UserGroupMembersEntry) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UserGroupMembersEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UserGroupMembersEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupID", wireType) + } + m.GroupID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Members = append(m.Members, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/subspaces/types/genesis_test.go b/x/subspaces/types/genesis_test.go new file mode 100644 index 0000000000..b30ea808a1 --- /dev/null +++ b/x/subspaces/types/genesis_test.go @@ -0,0 +1,605 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + "github.com/stretchr/testify/require" +) + +func TestACLEntry_Validate(t *testing.T) { + testCases := []struct { + name string + entry types.ACLEntry + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + entry: types.NewACLEntry( + 0, + "cosmos19gz9jn5pl6ke6qg5s4gt9ga9my7w8a0x3ar0qy", + types.PermissionWrite, + ), + shouldErr: true, + }, + { + name: "invalid user returns no error", + entry: types.NewACLEntry( + 1, + "cosmos19gz9jn5pl6ke6", + types.PermissionWrite, + ), + shouldErr: true, + }, + { + name: "valid user entry returns no error", + entry: types.NewACLEntry( + 1, + "cosmos1vkuuth0rak58x36m7wuzj7ztttxh26fhqcfxm0", + types.PermissionEverything, + ), + shouldErr: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.entry.Validate() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +// ------------------------------------------------------------------------------------------------------------------- + +func TestUserGroupMembersEntry_Validate(t *testing.T) { + testCases := []struct { + name string + entry types.UserGroupMembersEntry + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + entry: types.NewUserGroupMembersEntry(0, 1, nil), + shouldErr: true, + }, + { + name: "invalid group id returns error", + entry: types.NewUserGroupMembersEntry(1, 0, nil), + shouldErr: true, + }, + { + name: "invalid member returns error", + entry: types.NewUserGroupMembersEntry(1, 1, []string{ + "invalid-user", + }), + shouldErr: true, + }, + { + name: "valid entry returns no error", + entry: types.NewUserGroupMembersEntry(1, 1, []string{ + "cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e", + "cosmos19gz9jn5pl6ke6qg5s4gt9ga9my7w8a0x3ar0qy", + }), + shouldErr: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.entry.Validate() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +// ------------------------------------------------------------------------------------------------------------------- + +func TestValidateGenesis(t *testing.T) { + testCases := []struct { + name string + genesis *types.GenesisState + shouldErr bool + }{ + { + name: "invalid initial subspace id returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + types.NewGenesisSubspace( + types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1vkuuth0rak58x36m7wuzj7ztttxh26fhqcfxm0", + "cosmos1vkuuth0rak58x36m7wuzj7ztttxh26fhqcfxm0", + "cosmos1vkuuth0rak58x36m7wuzj7ztttxh26fhqcfxm0", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + nil, + nil, + ), + shouldErr: true, + }, + { + name: "invalid subspace returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 0, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + nil, + nil, + ), + shouldErr: true, + }, + { + name: "duplicated subspace returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "Another test subspace", + "This is another test subspace", + "cosmos1vkuuth0rak58x36m7wuzj7ztttxh26fhqcfxm0", + "cosmos1vkuuth0rak58x36m7wuzj7ztttxh26fhqcfxm0", + "cosmos1vkuuth0rak58x36m7wuzj7ztttxh26fhqcfxm0", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + nil, + nil, + ), + shouldErr: true, + }, + { + name: "invalid ACL entry returns error", + genesis: types.NewGenesisState( + 1, + nil, + []types.ACLEntry{ + types.NewACLEntry(0, "group", types.PermissionWrite), + }, + nil, + nil, + ), + shouldErr: true, + }, + { + name: "duplicated ACL entry returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + []types.ACLEntry{ + types.NewACLEntry(1, "cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd", types.PermissionWrite), + types.NewACLEntry(1, "cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd", types.PermissionSetPermissions), + }, + nil, + nil, + ), + shouldErr: true, + }, + { + name: "ACL entry without subspace returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + []types.ACLEntry{ + types.NewACLEntry(1, "cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd", types.PermissionWrite), + types.NewACLEntry(2, "cosmos15p3m7a93luselt80ffzpf4jwtn9ama34ray0nd", types.PermissionSetPermissions), + }, + nil, + nil, + ), + shouldErr: true, + }, + { + name: "invalid group returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + []types.UserGroup{ + types.NewUserGroup( + 1, + 0, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + nil, + ), + shouldErr: true, + }, + { + name: "duplicated group returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + nil, + ), + shouldErr: true, + }, + { + name: "group without subspace returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + types.NewUserGroup( + 1, + 2, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + nil, + ), + shouldErr: true, + }, + { + name: "invalid initial group id returns error", + genesis: types.NewGenesisState( + 1, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + nil, + ), + shouldErr: true, + }, + { + name: "invalid group members entry returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + []types.UserGroupMembersEntry{ + types.NewUserGroupMembersEntry(1, 0, nil), + }, + ), + shouldErr: true, + }, + { + name: "duplicated group members entry returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + []types.UserGroupMembersEntry{ + types.NewUserGroupMembersEntry(1, 1, nil), + types.NewUserGroupMembersEntry(1, 1, nil), + }, + ), + shouldErr: true, + }, + { + name: "group members entry without group returns error", + genesis: types.NewGenesisState( + 2, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "This is a test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 1, + ), + }, + nil, + []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + []types.UserGroupMembersEntry{ + types.NewUserGroupMembersEntry(1, 1, nil), + types.NewUserGroupMembersEntry(1, 2, nil), + }, + ), + shouldErr: true, + }, + { + name: "default genesis returns no error", + genesis: types.DefaultGenesisState(), + shouldErr: false, + }, + { + name: "valid genesis state returns no error", + genesis: types.NewGenesisState( + 3, + []types.GenesisSubspace{ + types.NewGenesisSubspace( + types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + 2, + ), + types.NewGenesisSubspace( + types.NewSubspace( + 2, + "Another test subspace", + "This is another test subspace", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + time.Date(2020, 1, 2, 12, 00, 00, 000, time.UTC), + ), + 2, + ), + }, + []types.ACLEntry{ + types.NewACLEntry(1, "cosmos19gz9jn5pl6ke6qg5s4gt9ga9my7w8a0x3ar0qy", types.PermissionWrite), + types.NewACLEntry(2, "cosmos1nv9kkuads7f627q2zf4k9kwdudx709rjck3s7e", types.PermissionManageGroups), + }, + []types.UserGroup{ + types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + types.NewUserGroup( + 2, + 1, + "Another test group", + "This is another test group", + types.PermissionWrite, + ), + }, + []types.UserGroupMembersEntry{ + types.NewUserGroupMembersEntry(1, 1, []string{ + "cosmos1a0cj0j6ujn2xap8p40y6648d0w2npytw3xvenm", + }), + types.NewUserGroupMembersEntry(2, 1, []string{ + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + }), + }, + ), + shouldErr: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := types.ValidateGenesis(tc.genesis) + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/subspaces/types/hooks.go b/x/subspaces/types/hooks.go new file mode 100644 index 0000000000..ebc7d19693 --- /dev/null +++ b/x/subspaces/types/hooks.go @@ -0,0 +1,92 @@ +package types + +// DONTCOVER + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Event Hooks +// These can be utilized to communicate between a subspaces keeper and another +// keeper which must take particular actions when subspaces/groups/permissions change +// state. The second keeper must implement this interface, which then the +// subspaces keeper can call. + +// SubspacesHooks event hooks for subspaces objects (noalias) +type SubspacesHooks interface { + AfterSubspaceSaved(ctx sdk.Context, subspaceID uint64) // Must be called when a subspace is saved + AfterSubspaceDeleted(ctx sdk.Context, subspaceID uint64) // Must be called when a subspace is deleted + + AfterSubspaceGroupSaved(ctx sdk.Context, subspaceID uint64, groupID uint32) // Must be called when a subspace group is created + AfterSubspaceGroupMemberAdded(ctx sdk.Context, subspaceID uint64, groupID uint32, user sdk.AccAddress) // Must be called when a user is added to a group + AfterSubspaceGroupMemberRemoved(ctx sdk.Context, subspaceID uint64, groupID uint32, user sdk.AccAddress) // Must be called when a user is removed from a group + AfterSubspaceGroupDeleted(ctx sdk.Context, subspaceID uint64, groupID uint32) // Must be called when a subspace group is deleted + + AfterUserPermissionSet(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress, permissions Permission) // Must be called when a permission is set for a user + AfterUserPermissionRemoved(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress) // Must be called when a permission is removed for a user +} + +// -------------------------------------------------------------------------------------------------------------------- + +// MultiSubspacesHooks combines multiple subspaces hooks, all hook functions are run in array sequence +type MultiSubspacesHooks []SubspacesHooks + +func NewMultiSubspacesHooks(hooks ...SubspacesHooks) MultiSubspacesHooks { + return hooks +} + +// AfterSubspaceSaved implements SubspacesHook +func (h MultiSubspacesHooks) AfterSubspaceSaved(ctx sdk.Context, subspaceID uint64) { + for _, hook := range h { + hook.AfterSubspaceSaved(ctx, subspaceID) + } +} + +// AfterSubspaceDeleted implements SubspacesHook +func (h MultiSubspacesHooks) AfterSubspaceDeleted(ctx sdk.Context, subspaceID uint64) { + for _, hook := range h { + hook.AfterSubspaceDeleted(ctx, subspaceID) + } +} + +// AfterSubspaceGroupSaved implements SubspacesHook +func (h MultiSubspacesHooks) AfterSubspaceGroupSaved(ctx sdk.Context, subspaceID uint64, groupID uint32) { + for _, hook := range h { + hook.AfterSubspaceGroupSaved(ctx, subspaceID, groupID) + } +} + +// AfterSubspaceGroupMemberAdded implements SubspacesHook +func (h MultiSubspacesHooks) AfterSubspaceGroupMemberAdded(ctx sdk.Context, subspaceID uint64, groupID uint32, user sdk.AccAddress) { + for _, hook := range h { + hook.AfterSubspaceGroupMemberAdded(ctx, subspaceID, groupID, user) + } +} + +// AfterSubspaceGroupMemberRemoved implements SubspacesHook +func (h MultiSubspacesHooks) AfterSubspaceGroupMemberRemoved(ctx sdk.Context, subspaceID uint64, groupID uint32, user sdk.AccAddress) { + for _, hook := range h { + hook.AfterSubspaceGroupMemberRemoved(ctx, subspaceID, groupID, user) + } +} + +// AfterSubspaceGroupDeleted implements SubspacesHook +func (h MultiSubspacesHooks) AfterSubspaceGroupDeleted(ctx sdk.Context, subspaceID uint64, groupID uint32) { + for _, hook := range h { + hook.AfterSubspaceGroupDeleted(ctx, subspaceID, groupID) + } +} + +// AfterUserPermissionSet implements SubspacesHook +func (h MultiSubspacesHooks) AfterUserPermissionSet(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress, permissions Permission) { + for _, hook := range h { + hook.AfterUserPermissionSet(ctx, subspaceID, user, permissions) + } +} + +// AfterUserPermissionRemoved implements SubspacesHook +func (h MultiSubspacesHooks) AfterUserPermissionRemoved(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress) { + for _, hook := range h { + hook.AfterUserPermissionRemoved(ctx, subspaceID, user) + } +} diff --git a/x/subspaces/types/keys.go b/x/subspaces/types/keys.go new file mode 100644 index 0000000000..458c1b8af6 --- /dev/null +++ b/x/subspaces/types/keys.go @@ -0,0 +1,116 @@ +package types + +import ( + "encoding/binary" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// DONTCOVER + +const ( + ModuleName = "subspaces" + RouterKey = ModuleName + StoreKey = ModuleName + + ActionCreateSubspace = "create_subspace" + ActionEditSubspace = "edit_subspace" + ActionDeleteSubspace = "delete_subspace" + ActionCreateUserGroup = "create_user_group" + ActionEditUserGroup = "edit_user_group" + ActionSetUserGroupPermissions = "set_group_permissions" + ActionDeleteUserGroup = "delete_user_group" + ActionAddUserToUserGroup = "add_user_to_user_group" + ActionRemoveUserFromUserGroup = "remove_user_from_user_group" + ActionSetUserPermissions = "set_user_permissions" + + QuerierRoute = ModuleName + + DoNotModify = "[do-not-modify]" +) + +var ( + SubspaceIDKey = []byte{0x00} + SubspacePrefix = []byte{0x01} + GroupIDPrefix = []byte{0x02} + GroupsPrefix = []byte{0x03} + GroupMembersStorePrefix = []byte{0x04} + UserPermissionsStorePrefix = []byte{0x05} +) + +// GetSubspaceIDBytes returns the byte representation of the subspaceID +func GetSubspaceIDBytes(subspaceID uint64) (subspaceIDBz []byte) { + subspaceIDBz = make([]byte, 8) + binary.BigEndian.PutUint64(subspaceIDBz, subspaceID) + return +} + +// GetSubspaceIDFromBytes returns subspaceID in uint64 format from a byte array +func GetSubspaceIDFromBytes(bz []byte) (subspaceID uint64) { + return binary.BigEndian.Uint64(bz) +} + +// SubspaceKey returns the key for a specific subspace +func SubspaceKey(subspaceID uint64) []byte { + return append(SubspacePrefix, GetSubspaceIDBytes(subspaceID)...) +} + +// PermissionsStoreKey returns the key used to store the entire ACL for a given subspace +func PermissionsStoreKey(subspaceID uint64) []byte { + return append(UserPermissionsStorePrefix, GetSubspaceIDBytes(subspaceID)...) +} + +func GetAddressBytes(user sdk.AccAddress) []byte { + return user +} + +func GetAddressFromBytes(bz []byte) sdk.AccAddress { + return bz +} + +// -------------------------------------------------------------------------------------------------------------------- + +// GroupIDStoreKey returns the store key that is used to store the group id to be used next for the given subspace +func GroupIDStoreKey(subspaceID uint64) []byte { + return append(GroupIDPrefix, GetSubspaceIDBytes(subspaceID)...) +} + +// GetGroupIDBytes returns the byte representation of the groupID +func GetGroupIDBytes(groupID uint32) (groupIDBz []byte) { + groupIDBz = make([]byte, 4) + binary.BigEndian.PutUint32(groupIDBz, groupID) + return +} + +// GetGroupIDFromBytes returns groupID in uint32 format from a byte array +func GetGroupIDFromBytes(bz []byte) (subspaceID uint32) { + return binary.BigEndian.Uint32(bz) +} + +// GroupsStoreKey returns the key used to store all the groups of a given subspace +func GroupsStoreKey(subspaceID uint64) []byte { + return append(GroupsPrefix, GetSubspaceIDBytes(subspaceID)...) +} + +// GroupStoreKey returns the key used to store a group for a subspace +func GroupStoreKey(subspaceID uint64, groupID uint32) []byte { + return append(GroupsStoreKey(subspaceID), GetGroupIDBytes(groupID)...) +} + +// GroupMembersStoreKey returns the key used to store all the members of the given group inside the given subspace +func GroupMembersStoreKey(subspaceID uint64, groupID uint32) []byte { + return append(append(GroupMembersStorePrefix, GetSubspaceIDBytes(subspaceID)...), GetGroupIDBytes(groupID)...) +} + +// GroupMemberStoreKey returns the key used to store the membership of the given user to the +// specified group inside the provided subspace +func GroupMemberStoreKey(subspaceID uint64, groupID uint32, user sdk.AccAddress) []byte { + return append(GroupMembersStoreKey(subspaceID, groupID), GetAddressBytes(user)...) +} + +// -------------------------------------------------------------------------------------------------------------------- + +// UserPermissionStoreKey returns the key used to store the permission for the given user inside the given subspace +func UserPermissionStoreKey(subspaceID uint64, user sdk.AccAddress) []byte { + return append(PermissionsStoreKey(subspaceID), GetAddressBytes(user)...) +} diff --git a/x/subspaces/types/models.go b/x/subspaces/types/models.go new file mode 100644 index 0000000000..cf5968a40c --- /dev/null +++ b/x/subspaces/types/models.go @@ -0,0 +1,229 @@ +package types + +import ( + "fmt" + "strconv" + "strings" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// ParseSubspaceID parses the given value as a subspace id, returning an error if it's invalid +func ParseSubspaceID(value string) (uint64, error) { + if value == "" { + return 0, nil + } + + subspaceID, err := strconv.ParseUint(value, 10, 64) + if err != nil { + return 0, fmt.Errorf("invalid subspace id: %s", err) + } + return subspaceID, nil +} + +// NewSubspace is a constructor for the Subspace type +func NewSubspace(subspaceID uint64, name, description, treasury, owner, creator string, creationTime time.Time) Subspace { + return Subspace{ + ID: subspaceID, + Name: name, + Description: description, + Treasury: treasury, + Owner: owner, + Creator: creator, + CreationTime: creationTime, + } +} + +// Validate will perform some checks to ensure the subspace validity +func (sub Subspace) Validate() error { + if sub.ID == 0 { + return fmt.Errorf("invalid subspace id: %d", sub.ID) + } + + if strings.TrimSpace(sub.Name) == "" { + return fmt.Errorf("subspace name cannot be empty or blank") + } + + if sub.Treasury != "" { + _, err := sdk.AccAddressFromBech32(sub.Treasury) + if err != nil { + return fmt.Errorf("invalid treasury address: %s", sub.Treasury) + } + } + + _, err := sdk.AccAddressFromBech32(sub.Owner) + if err != nil { + return fmt.Errorf("invalid owner address: %s", sub.Owner) + } + + _, err = sdk.AccAddressFromBech32(sub.Creator) + if err != nil { + return fmt.Errorf("invalid creator address: %s", sub.Creator) + } + + if sub.CreationTime.IsZero() { + return fmt.Errorf("invalid subspace creation time: %s", sub.CreationTime) + } + + return nil +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SubspaceUpdate contains all the data that can be updated about a subspace. +// When performing an update, if a field should not be edited then it must be set to types.DoNotModify +type SubspaceUpdate struct { + Name string + Description string + Treasury string + Owner string +} + +// NewSubspaceUpdate builds a new SubspaceUpdate instance containing the given data +func NewSubspaceUpdate(name, description, treasury, owner string) *SubspaceUpdate { + return &SubspaceUpdate{ + Name: name, + Description: description, + Treasury: treasury, + Owner: owner, + } +} + +// Update updates the fields of a given subspace without validating it. +// Before storing the updated subspace, a validation with Validate() should +// be performed. +func (sub Subspace) Update(update *SubspaceUpdate) Subspace { + if update.Name == DoNotModify { + update.Name = sub.Name + } + + if update.Description == DoNotModify { + update.Description = sub.Description + } + + if update.Treasury == DoNotModify { + update.Treasury = sub.Treasury + } + + if update.Owner == DoNotModify { + update.Owner = sub.Owner + } + + return NewSubspace( + sub.ID, + update.Name, + update.Description, + update.Treasury, + update.Owner, + sub.Creator, + sub.CreationTime, + ) +} + +// -------------------------------------------------------------------------------------------------------------------- + +// ParseGroupID parses the given value as a group id, returning an error if it's invalid +func ParseGroupID(value string) (uint32, error) { + if value == "" { + return 0, nil + } + + groupID, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return 0, fmt.Errorf("invalid group id: %s", err) + } + return uint32(groupID), nil +} + +// NewUserGroup returns a new UserGroup instance +func NewUserGroup(subspaceID uint64, id uint32, name, description string, permissions Permission) UserGroup { + return UserGroup{ + SubspaceID: subspaceID, + ID: id, + Name: name, + Description: description, + Permissions: permissions, + } +} + +// Validate returns an error if something is wrong within the group data +func (group UserGroup) Validate() error { + if group.SubspaceID == 0 { + return fmt.Errorf("invalid subspace id: %d", group.SubspaceID) + } + + if group.ID == 0 { + return fmt.Errorf("invalid group id: %d", group.ID) + } + + if strings.TrimSpace(group.Name) == "" { + return fmt.Errorf("invalid group name: %s", group.Name) + } + + return nil +} + +// -------------------------------------------------------------------------------------------------------------------- + +// GroupUpdate contains all the data that can be updated about a group. +// When performing an update, if a field should not be edited then it must be set to types.DoNotModify +type GroupUpdate struct { + Name string + Description string +} + +// NewGroupUpdate builds a new SubspaceUpdate instance containing the given data +func NewGroupUpdate(name, description string) *GroupUpdate { + return &GroupUpdate{ + Name: name, + Description: description, + } +} + +// Update updates the fields of a given group without validating it. +// Before storing the updated group, a validation with Validate() should +// be performed. +func (group UserGroup) Update(update *GroupUpdate) UserGroup { + if update.Name == DoNotModify { + update.Name = group.Name + } + + if update.Description == DoNotModify { + update.Description = group.Description + } + + return NewUserGroup( + group.SubspaceID, + group.ID, + update.Name, + update.Description, + group.Permissions, + ) +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewPermissionDetailUser returns a new PermissionDetail for the user with the given address and permission value +func NewPermissionDetailUser(user string, permission Permission) PermissionDetail { + return PermissionDetail{ + Sum: &PermissionDetail_User_{ + User: &PermissionDetail_User{ + User: user, + Permission: permission, + }, + }, + } +} + +// NewPermissionDetailGroup returns a new PermissionDetail for the user with the given id and permission value +func NewPermissionDetailGroup(groupID uint32, permission Permission) PermissionDetail { + return PermissionDetail{ + Sum: &PermissionDetail_Group_{ + Group: &PermissionDetail_Group{ + GroupID: groupID, + Permission: permission, + }, + }, + } +} diff --git a/x/subspaces/types/models.pb.go b/x/subspaces/types/models.pb.go new file mode 100644 index 0000000000..b416cb8cee --- /dev/null +++ b/x/subspaces/types/models.pb.go @@ -0,0 +1,1883 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/subspaces/v1/models.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Subspace contains all the data of a Desmos subspace +type Subspace struct { + // Unique id that identifies the subspace + ID uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"` + // Human-readable name of the subspace + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` + // Optional description of this subspace + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` + // Represents the account that is associated with the subspace and + // should be used to connect external applications to verify this subspace + Treasury string `protobuf:"bytes,4,opt,name=treasury,proto3" json:"treasury,omitempty" yaml:"treasury"` + // Address of the user that owns the subspace + Owner string `protobuf:"bytes,5,opt,name=owner,proto3" json:"owner,omitempty" yaml:"owner"` + // Address of the subspace creator + Creator string `protobuf:"bytes,6,opt,name=creator,proto3" json:"creator,omitempty" yaml:"creator"` + // the creation time of the subspace + CreationTime time.Time `protobuf:"bytes,7,opt,name=creation_time,json=creationTime,proto3,stdtime" json:"creation_time" yaml:"creation_time"` +} + +func (m *Subspace) Reset() { *m = Subspace{} } +func (m *Subspace) String() string { return proto.CompactTextString(m) } +func (*Subspace) ProtoMessage() {} +func (*Subspace) Descriptor() ([]byte, []int) { + return fileDescriptor_58f218b6c9069791, []int{0} +} +func (m *Subspace) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Subspace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Subspace.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Subspace) XXX_Merge(src proto.Message) { + xxx_messageInfo_Subspace.Merge(m, src) +} +func (m *Subspace) XXX_Size() int { + return m.Size() +} +func (m *Subspace) XXX_DiscardUnknown() { + xxx_messageInfo_Subspace.DiscardUnknown(m) +} + +var xxx_messageInfo_Subspace proto.InternalMessageInfo + +func (m *Subspace) GetID() uint64 { + if m != nil { + return m.ID + } + return 0 +} + +func (m *Subspace) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Subspace) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *Subspace) GetTreasury() string { + if m != nil { + return m.Treasury + } + return "" +} + +func (m *Subspace) GetOwner() string { + if m != nil { + return m.Owner + } + return "" +} + +func (m *Subspace) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *Subspace) GetCreationTime() time.Time { + if m != nil { + return m.CreationTime + } + return time.Time{} +} + +// UserGroup represents a group of users +type UserGroup struct { + // ID of the subspace inside which this group exists + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + // Unique id that identifies the group + ID uint32 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty" yaml:"id"` + // Human-readable name of the user group + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` + // Optional description of this group + Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` + // Permissions that will be granted to all the users part of this group + Permissions uint32 `protobuf:"varint,5,opt,name=permissions,proto3" json:"permissions,omitempty" yaml:"permissions"` +} + +func (m *UserGroup) Reset() { *m = UserGroup{} } +func (m *UserGroup) String() string { return proto.CompactTextString(m) } +func (*UserGroup) ProtoMessage() {} +func (*UserGroup) Descriptor() ([]byte, []int) { + return fileDescriptor_58f218b6c9069791, []int{1} +} +func (m *UserGroup) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UserGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UserGroup.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *UserGroup) XXX_Merge(src proto.Message) { + xxx_messageInfo_UserGroup.Merge(m, src) +} +func (m *UserGroup) XXX_Size() int { + return m.Size() +} +func (m *UserGroup) XXX_DiscardUnknown() { + xxx_messageInfo_UserGroup.DiscardUnknown(m) +} + +var xxx_messageInfo_UserGroup proto.InternalMessageInfo + +func (m *UserGroup) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *UserGroup) GetID() uint32 { + if m != nil { + return m.ID + } + return 0 +} + +func (m *UserGroup) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *UserGroup) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *UserGroup) GetPermissions() uint32 { + if m != nil { + return m.Permissions + } + return 0 +} + +// PermissionDetail contains the details data of a permission +type PermissionDetail struct { + // sum is the oneof that specifies whether this represents a user or + // group permission detail + // + // Types that are valid to be assigned to Sum: + // *PermissionDetail_User_ + // *PermissionDetail_Group_ + Sum isPermissionDetail_Sum `protobuf_oneof:"sum"` +} + +func (m *PermissionDetail) Reset() { *m = PermissionDetail{} } +func (m *PermissionDetail) String() string { return proto.CompactTextString(m) } +func (*PermissionDetail) ProtoMessage() {} +func (*PermissionDetail) Descriptor() ([]byte, []int) { + return fileDescriptor_58f218b6c9069791, []int{2} +} +func (m *PermissionDetail) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PermissionDetail) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PermissionDetail.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PermissionDetail) XXX_Merge(src proto.Message) { + xxx_messageInfo_PermissionDetail.Merge(m, src) +} +func (m *PermissionDetail) XXX_Size() int { + return m.Size() +} +func (m *PermissionDetail) XXX_DiscardUnknown() { + xxx_messageInfo_PermissionDetail.DiscardUnknown(m) +} + +var xxx_messageInfo_PermissionDetail proto.InternalMessageInfo + +type isPermissionDetail_Sum interface { + isPermissionDetail_Sum() + Equal(interface{}) bool + MarshalTo([]byte) (int, error) + Size() int +} + +type PermissionDetail_User_ struct { + User *PermissionDetail_User `protobuf:"bytes,1,opt,name=user,proto3,oneof" json:"user,omitempty"` +} +type PermissionDetail_Group_ struct { + Group *PermissionDetail_Group `protobuf:"bytes,2,opt,name=group,proto3,oneof" json:"group,omitempty"` +} + +func (*PermissionDetail_User_) isPermissionDetail_Sum() {} +func (*PermissionDetail_Group_) isPermissionDetail_Sum() {} + +func (m *PermissionDetail) GetSum() isPermissionDetail_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *PermissionDetail) GetUser() *PermissionDetail_User { + if x, ok := m.GetSum().(*PermissionDetail_User_); ok { + return x.User + } + return nil +} + +func (m *PermissionDetail) GetGroup() *PermissionDetail_Group { + if x, ok := m.GetSum().(*PermissionDetail_Group_); ok { + return x.Group + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*PermissionDetail) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*PermissionDetail_User_)(nil), + (*PermissionDetail_Group_)(nil), + } +} + +// Success is a permission that has been set to a specific user +type PermissionDetail_User struct { + // User for which the permission was set + User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty" yaml:"user"` + // Permission set to the user + Permission uint32 `protobuf:"varint,2,opt,name=permission,proto3" json:"permission,omitempty" yaml:"permission"` +} + +func (m *PermissionDetail_User) Reset() { *m = PermissionDetail_User{} } +func (m *PermissionDetail_User) String() string { return proto.CompactTextString(m) } +func (*PermissionDetail_User) ProtoMessage() {} +func (*PermissionDetail_User) Descriptor() ([]byte, []int) { + return fileDescriptor_58f218b6c9069791, []int{2, 0} +} +func (m *PermissionDetail_User) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PermissionDetail_User) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PermissionDetail_User.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PermissionDetail_User) XXX_Merge(src proto.Message) { + xxx_messageInfo_PermissionDetail_User.Merge(m, src) +} +func (m *PermissionDetail_User) XXX_Size() int { + return m.Size() +} +func (m *PermissionDetail_User) XXX_DiscardUnknown() { + xxx_messageInfo_PermissionDetail_User.DiscardUnknown(m) +} + +var xxx_messageInfo_PermissionDetail_User proto.InternalMessageInfo + +// Group is a permission that has been set to a user group +type PermissionDetail_Group struct { + // Error that is associated with the failure + GroupID uint32 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty" yaml:"error"` + // Permission set to the group + Permission uint32 `protobuf:"varint,2,opt,name=permission,proto3" json:"permission,omitempty"` +} + +func (m *PermissionDetail_Group) Reset() { *m = PermissionDetail_Group{} } +func (m *PermissionDetail_Group) String() string { return proto.CompactTextString(m) } +func (*PermissionDetail_Group) ProtoMessage() {} +func (*PermissionDetail_Group) Descriptor() ([]byte, []int) { + return fileDescriptor_58f218b6c9069791, []int{2, 1} +} +func (m *PermissionDetail_Group) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PermissionDetail_Group) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PermissionDetail_Group.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PermissionDetail_Group) XXX_Merge(src proto.Message) { + xxx_messageInfo_PermissionDetail_Group.Merge(m, src) +} +func (m *PermissionDetail_Group) XXX_Size() int { + return m.Size() +} +func (m *PermissionDetail_Group) XXX_DiscardUnknown() { + xxx_messageInfo_PermissionDetail_Group.DiscardUnknown(m) +} + +var xxx_messageInfo_PermissionDetail_Group proto.InternalMessageInfo + +func init() { + proto.RegisterType((*Subspace)(nil), "desmos.subspaces.v1.Subspace") + proto.RegisterType((*UserGroup)(nil), "desmos.subspaces.v1.UserGroup") + proto.RegisterType((*PermissionDetail)(nil), "desmos.subspaces.v1.PermissionDetail") + proto.RegisterType((*PermissionDetail_User)(nil), "desmos.subspaces.v1.PermissionDetail.User") + proto.RegisterType((*PermissionDetail_Group)(nil), "desmos.subspaces.v1.PermissionDetail.Group") +} + +func init() { proto.RegisterFile("desmos/subspaces/v1/models.proto", fileDescriptor_58f218b6c9069791) } + +var fileDescriptor_58f218b6c9069791 = []byte{ + // 635 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0x4f, 0x6f, 0xd3, 0x30, + 0x00, 0xc5, 0x93, 0xfe, 0xd9, 0x3a, 0x67, 0x65, 0xc3, 0x1b, 0x28, 0x2a, 0x52, 0x5c, 0x79, 0x08, + 0x4d, 0xfc, 0x49, 0xb4, 0x22, 0xd0, 0xb4, 0x13, 0x2a, 0x43, 0x6c, 0x12, 0x07, 0x14, 0xe0, 0xc2, + 0x65, 0x4a, 0x1b, 0x53, 0x2c, 0x35, 0x75, 0x64, 0x27, 0x83, 0x5d, 0xe1, 0xc2, 0x71, 0x47, 0xc4, + 0x69, 0x1f, 0x67, 0xc7, 0x1d, 0x39, 0x19, 0xd4, 0x5e, 0x38, 0xe7, 0x13, 0xa0, 0xd8, 0x49, 0x17, + 0xc6, 0x24, 0xc6, 0xcd, 0xf1, 0xfb, 0x3d, 0xdb, 0x7d, 0xcf, 0x2e, 0xe8, 0x86, 0x44, 0x44, 0x4c, + 0x78, 0x22, 0x1d, 0x88, 0x38, 0x18, 0x12, 0xe1, 0x1d, 0x6e, 0x79, 0x11, 0x0b, 0xc9, 0x58, 0xb8, + 0x31, 0x67, 0x09, 0x83, 0x6b, 0x9a, 0x70, 0xe7, 0x84, 0x7b, 0xb8, 0xd5, 0x59, 0x1f, 0xb1, 0x11, + 0x53, 0xba, 0x97, 0x8f, 0x34, 0xda, 0x41, 0x23, 0xc6, 0x46, 0x63, 0xe2, 0xa9, 0xaf, 0x41, 0xfa, + 0xce, 0x4b, 0x68, 0x44, 0x44, 0x12, 0x44, 0xb1, 0x06, 0xf0, 0xa7, 0x3a, 0x68, 0xbd, 0x2a, 0xd6, + 0x81, 0x1b, 0xa0, 0x46, 0x43, 0xdb, 0xec, 0x9a, 0x9b, 0x8d, 0xfe, 0xda, 0x54, 0xa2, 0xda, 0xfe, + 0x6e, 0x26, 0xd1, 0xd2, 0x51, 0x10, 0x8d, 0x77, 0x30, 0x0d, 0xb1, 0x5f, 0xa3, 0x21, 0xdc, 0x00, + 0x8d, 0x49, 0x10, 0x11, 0xbb, 0xd6, 0x35, 0x37, 0x97, 0xfa, 0x2b, 0x99, 0x44, 0x96, 0x06, 0xf2, + 0x59, 0xec, 0x2b, 0x11, 0x6e, 0x03, 0x2b, 0x24, 0x62, 0xc8, 0x69, 0x9c, 0x50, 0x36, 0xb1, 0xeb, + 0x8a, 0xbd, 0x99, 0x49, 0x04, 0x35, 0x5b, 0x11, 0xb1, 0x5f, 0x45, 0xa1, 0x07, 0x5a, 0x09, 0x27, + 0x81, 0x48, 0xf9, 0x91, 0xdd, 0x50, 0xb6, 0xb5, 0x4c, 0xa2, 0x15, 0x6d, 0x2b, 0x15, 0xec, 0xcf, + 0x21, 0x78, 0x07, 0x34, 0xd9, 0x87, 0x09, 0xe1, 0x76, 0x53, 0xd1, 0xab, 0x99, 0x44, 0xcb, 0x9a, + 0x56, 0xd3, 0xd8, 0xd7, 0x32, 0xbc, 0x0f, 0x16, 0x87, 0x9c, 0x04, 0x09, 0xe3, 0xf6, 0x82, 0x22, + 0x61, 0x26, 0xd1, 0x35, 0x4d, 0x16, 0x02, 0xf6, 0x4b, 0x04, 0x06, 0xa0, 0xad, 0x86, 0x94, 0x4d, + 0x0e, 0xf2, 0xcc, 0xec, 0xc5, 0xae, 0xb9, 0x69, 0xf5, 0x3a, 0xae, 0x0e, 0xd4, 0x2d, 0x03, 0x75, + 0x5f, 0x97, 0x81, 0xf6, 0xbb, 0xa7, 0x12, 0x19, 0x99, 0x44, 0xeb, 0x95, 0x35, 0x4b, 0x3b, 0x3e, + 0xfe, 0x81, 0x4c, 0x7f, 0xb9, 0x9c, 0xcb, 0x4d, 0x3b, 0xad, 0xaf, 0x27, 0xc8, 0xfc, 0x75, 0x82, + 0x4c, 0xfc, 0xad, 0x06, 0x96, 0xde, 0x08, 0xc2, 0x9f, 0x73, 0x96, 0xc6, 0xf0, 0x19, 0xb0, 0xca, + 0x66, 0x0f, 0xe6, 0x75, 0xdc, 0x9e, 0x4a, 0x04, 0xca, 0xa2, 0x54, 0x2d, 0x45, 0x92, 0x15, 0x14, + 0xfb, 0xa0, 0xfc, 0xda, 0x0f, 0x8b, 0x32, 0xf3, 0x96, 0xda, 0xff, 0x2e, 0xb3, 0xfe, 0x1f, 0x65, + 0x36, 0xae, 0x5e, 0xe6, 0x36, 0xb0, 0x62, 0xc2, 0x23, 0x2a, 0x04, 0x65, 0x13, 0xa1, 0x1a, 0x6a, + 0x57, 0x9d, 0x15, 0x11, 0xfb, 0x55, 0xb4, 0x12, 0xce, 0xe7, 0x3a, 0x58, 0x7d, 0x39, 0x57, 0x76, + 0x49, 0x12, 0xd0, 0x31, 0x7c, 0x02, 0x1a, 0xa9, 0x20, 0x5c, 0x85, 0x63, 0xf5, 0xee, 0xba, 0x97, + 0xbc, 0x08, 0xf7, 0xa2, 0xc9, 0xcd, 0x23, 0xde, 0x33, 0x7c, 0xe5, 0x84, 0x4f, 0x41, 0x73, 0x94, + 0xc7, 0xad, 0x12, 0xb2, 0x7a, 0xf7, 0xae, 0xb6, 0x84, 0x6a, 0x68, 0xcf, 0xf0, 0xb5, 0xb7, 0x33, + 0x06, 0x8d, 0x7c, 0xd1, 0x3c, 0xc6, 0xf9, 0x71, 0xfe, 0x88, 0x31, 0x9f, 0xc5, 0xc5, 0x8e, 0x8f, + 0x00, 0x38, 0xff, 0x85, 0x45, 0x31, 0x37, 0x32, 0x89, 0xae, 0x5f, 0xcc, 0x02, 0xfb, 0x15, 0x70, + 0xa7, 0xf5, 0xe5, 0x04, 0x19, 0x79, 0x12, 0x1d, 0x0a, 0x9a, 0xfa, 0x86, 0x3c, 0x06, 0x2d, 0xb5, + 0x7f, 0x79, 0x3d, 0xda, 0xfd, 0x5b, 0x53, 0x89, 0x16, 0x95, 0xa8, 0x5a, 0x2e, 0x1e, 0x00, 0xe1, + 0x5c, 0x5d, 0x6a, 0x05, 0xef, 0x87, 0xd0, 0xf9, 0xfb, 0x04, 0x97, 0x6f, 0x75, 0x3e, 0xea, 0x37, + 0x41, 0x5d, 0xa4, 0x51, 0xff, 0xc5, 0xe9, 0xd4, 0x31, 0xcf, 0xa6, 0x8e, 0xf9, 0x73, 0xea, 0x98, + 0xc7, 0x33, 0xc7, 0x38, 0x9b, 0x39, 0xc6, 0xf7, 0x99, 0x63, 0xbc, 0xed, 0x8d, 0x68, 0xf2, 0x3e, + 0x1d, 0xb8, 0x43, 0x16, 0x79, 0x3a, 0xc3, 0x07, 0xe3, 0x60, 0x20, 0x8a, 0xb1, 0x77, 0xd8, 0xf3, + 0x3e, 0x56, 0xfe, 0xcb, 0x92, 0xa3, 0x98, 0x88, 0xc1, 0x82, 0x7a, 0x3e, 0x0f, 0x7f, 0x07, 0x00, + 0x00, 0xff, 0xff, 0x0c, 0x90, 0x85, 0x9f, 0xec, 0x04, 0x00, 0x00, +} + +func (this *Subspace) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Subspace) + if !ok { + that2, ok := that.(Subspace) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.ID != that1.ID { + return false + } + if this.Name != that1.Name { + return false + } + if this.Description != that1.Description { + return false + } + if this.Treasury != that1.Treasury { + return false + } + if this.Owner != that1.Owner { + return false + } + if this.Creator != that1.Creator { + return false + } + if !this.CreationTime.Equal(that1.CreationTime) { + return false + } + return true +} +func (this *UserGroup) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*UserGroup) + if !ok { + that2, ok := that.(UserGroup) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.SubspaceID != that1.SubspaceID { + return false + } + if this.ID != that1.ID { + return false + } + if this.Name != that1.Name { + return false + } + if this.Description != that1.Description { + return false + } + if this.Permissions != that1.Permissions { + return false + } + return true +} +func (this *PermissionDetail) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PermissionDetail) + if !ok { + that2, ok := that.(PermissionDetail) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if that1.Sum == nil { + if this.Sum != nil { + return false + } + } else if this.Sum == nil { + return false + } else if !this.Sum.Equal(that1.Sum) { + return false + } + return true +} +func (this *PermissionDetail_User_) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PermissionDetail_User_) + if !ok { + that2, ok := that.(PermissionDetail_User_) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.User.Equal(that1.User) { + return false + } + return true +} +func (this *PermissionDetail_Group_) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PermissionDetail_Group_) + if !ok { + that2, ok := that.(PermissionDetail_Group_) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Group.Equal(that1.Group) { + return false + } + return true +} +func (this *PermissionDetail_User) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PermissionDetail_User) + if !ok { + that2, ok := that.(PermissionDetail_User) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.User != that1.User { + return false + } + if this.Permission != that1.Permission { + return false + } + return true +} +func (this *PermissionDetail_Group) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PermissionDetail_Group) + if !ok { + that2, ok := that.(PermissionDetail_Group) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.GroupID != that1.GroupID { + return false + } + if this.Permission != that1.Permission { + return false + } + return true +} +func (m *Subspace) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Subspace) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Subspace) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreationTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.CreationTime):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintModels(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x3a + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintModels(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0x32 + } + if len(m.Owner) > 0 { + i -= len(m.Owner) + copy(dAtA[i:], m.Owner) + i = encodeVarintModels(dAtA, i, uint64(len(m.Owner))) + i-- + dAtA[i] = 0x2a + } + if len(m.Treasury) > 0 { + i -= len(m.Treasury) + copy(dAtA[i:], m.Treasury) + i = encodeVarintModels(dAtA, i, uint64(len(m.Treasury))) + i-- + dAtA[i] = 0x22 + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintModels(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x1a + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintModels(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x12 + } + if m.ID != 0 { + i = encodeVarintModels(dAtA, i, uint64(m.ID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *UserGroup) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UserGroup) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UserGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Permissions != 0 { + i = encodeVarintModels(dAtA, i, uint64(m.Permissions)) + i-- + dAtA[i] = 0x28 + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintModels(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x22 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintModels(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x1a + } + if m.ID != 0 { + i = encodeVarintModels(dAtA, i, uint64(m.ID)) + i-- + dAtA[i] = 0x10 + } + if m.SubspaceID != 0 { + i = encodeVarintModels(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *PermissionDetail) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PermissionDetail) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PermissionDetail) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *PermissionDetail_User_) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PermissionDetail_User_) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.User != nil { + { + size, err := m.User.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintModels(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *PermissionDetail_Group_) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PermissionDetail_Group_) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Group != nil { + { + size, err := m.Group.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintModels(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *PermissionDetail_User) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PermissionDetail_User) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PermissionDetail_User) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Permission != 0 { + i = encodeVarintModels(dAtA, i, uint64(m.Permission)) + i-- + dAtA[i] = 0x10 + } + if len(m.User) > 0 { + i -= len(m.User) + copy(dAtA[i:], m.User) + i = encodeVarintModels(dAtA, i, uint64(len(m.User))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PermissionDetail_Group) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PermissionDetail_Group) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PermissionDetail_Group) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Permission != 0 { + i = encodeVarintModels(dAtA, i, uint64(m.Permission)) + i-- + dAtA[i] = 0x10 + } + if m.GroupID != 0 { + i = encodeVarintModels(dAtA, i, uint64(m.GroupID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintModels(dAtA []byte, offset int, v uint64) int { + offset -= sovModels(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Subspace) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ID != 0 { + n += 1 + sovModels(uint64(m.ID)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovModels(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovModels(uint64(l)) + } + l = len(m.Treasury) + if l > 0 { + n += 1 + l + sovModels(uint64(l)) + } + l = len(m.Owner) + if l > 0 { + n += 1 + l + sovModels(uint64(l)) + } + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovModels(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreationTime) + n += 1 + l + sovModels(uint64(l)) + return n +} + +func (m *UserGroup) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovModels(uint64(m.SubspaceID)) + } + if m.ID != 0 { + n += 1 + sovModels(uint64(m.ID)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovModels(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovModels(uint64(l)) + } + if m.Permissions != 0 { + n += 1 + sovModels(uint64(m.Permissions)) + } + return n +} + +func (m *PermissionDetail) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *PermissionDetail_User_) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.User != nil { + l = m.User.Size() + n += 1 + l + sovModels(uint64(l)) + } + return n +} +func (m *PermissionDetail_Group_) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Group != nil { + l = m.Group.Size() + n += 1 + l + sovModels(uint64(l)) + } + return n +} +func (m *PermissionDetail_User) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.User) + if l > 0 { + n += 1 + l + sovModels(uint64(l)) + } + if m.Permission != 0 { + n += 1 + sovModels(uint64(m.Permission)) + } + return n +} + +func (m *PermissionDetail_Group) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupID != 0 { + n += 1 + sovModels(uint64(m.GroupID)) + } + if m.Permission != 0 { + n += 1 + sovModels(uint64(m.Permission)) + } + return n +} + +func sovModels(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozModels(x uint64) (n int) { + return sovModels(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Subspace) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Subspace: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Subspace: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + m.ID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Treasury", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Treasury = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Owner = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CreationTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreationTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipModels(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModels + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *UserGroup) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UserGroup: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UserGroup: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + m.ID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) + } + m.Permissions = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Permissions |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipModels(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModels + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PermissionDetail) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PermissionDetail: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PermissionDetail: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PermissionDetail_User{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &PermissionDetail_User_{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PermissionDetail_Group{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &PermissionDetail_Group_{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipModels(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModels + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PermissionDetail_User) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: User: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: User: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.User = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Permission", wireType) + } + m.Permission = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Permission |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipModels(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModels + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PermissionDetail_Group) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Group: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Group: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupID", wireType) + } + m.GroupID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Permission", wireType) + } + m.Permission = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Permission |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipModels(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModels + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipModels(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModels + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModels + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModels + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthModels + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupModels + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthModels + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthModels = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowModels = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupModels = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/subspaces/types/models_test.go b/x/subspaces/types/models_test.go new file mode 100644 index 0000000000..34af79b913 --- /dev/null +++ b/x/subspaces/types/models_test.go @@ -0,0 +1,394 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + "github.com/stretchr/testify/require" +) + +func TestParseSubspaceID(t *testing.T) { + testCases := []struct { + name string + value string + shouldErr bool + expID uint64 + }{ + { + name: "invalid id returns error", + value: "id", + shouldErr: true, + }, + { + name: "empty value returns zero", + value: "", + shouldErr: false, + expID: 0, + }, + { + name: "valid id returns correct value", + value: "2", + shouldErr: false, + expID: 2, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + id, err := types.ParseSubspaceID(tc.value) + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.expID, id) + } + }) + } +} + +func TestSubspace_Validate(t *testing.T) { + testCases := []struct { + name string + subspace types.Subspace + shouldErr bool + }{ + { + name: "invalid id returns error", + subspace: types.NewSubspace( + 0, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + shouldErr: true, + }, + { + name: "invalid name returns error", + subspace: types.NewSubspace( + 1, + "", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + shouldErr: true, + }, + { + name: "invalid treasury returns error", + subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsx", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + shouldErr: true, + }, + { + name: "invalid owner returns error", + subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + shouldErr: true, + }, + { + name: "invalid creator returns error", + subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zw", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + shouldErr: true, + }, + { + name: "invalid creation time returns error", + subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Time{}, + ), + shouldErr: true, + }, + { + name: "valid subspace returns no error", + subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + shouldErr: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.subspace.Validate() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +func TestSubspace_Update(t *testing.T) { + testCases := []struct { + name string + subspace types.Subspace + update *types.SubspaceUpdate + expResult types.Subspace + }{ + { + name: "nothing is updated when using DoNotModify", + subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + update: types.NewSubspaceUpdate( + types.DoNotModify, + types.DoNotModify, + types.DoNotModify, + types.DoNotModify, + ), + expResult: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + }, + { + name: "each field is updated when edited", + subspace: types.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + update: types.NewSubspaceUpdate( + "New subspace name", + "New subspace description", + "cosmos1l6rkljkrh5g0vyeh9m8tsl4cy626shunv6ksz7", + "cosmos10ya9y35qkf4puaklx5fs07sxfxqncx9usgsnz6", + ), + expResult: types.NewSubspace( + 1, + "New subspace name", + "New subspace description", + "cosmos1l6rkljkrh5g0vyeh9m8tsl4cy626shunv6ksz7", + "cosmos10ya9y35qkf4puaklx5fs07sxfxqncx9usgsnz6", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + ), + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + result := tc.subspace.Update(tc.update) + require.Equal(t, tc.expResult, result) + }) + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +func TestParseUserGroupID(t *testing.T) { + testCases := []struct { + name string + value string + shouldErr bool + expID uint32 + }{ + { + name: "invalid id returns error", + value: "id", + shouldErr: true, + }, + { + name: "empty value returns zero", + value: "", + shouldErr: false, + expID: 0, + }, + { + name: "valid id returns correct value", + value: "2", + shouldErr: false, + expID: 2, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + id, err := types.ParseGroupID(tc.value) + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.expID, id) + } + }) + } +} + +func TestUserGroup_Validate(t *testing.T) { + testCases := []struct { + name string + group types.UserGroup + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + group: types.NewUserGroup( + 0, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + shouldErr: true, + }, + { + name: "invalid group name returns error - empty", + group: types.NewUserGroup( + 1, + 1, + "", + "This is a test group", + types.PermissionWrite, + ), + shouldErr: true, + }, + { + name: "invalid group name returns error - blank", + group: types.NewUserGroup( + 1, + 1, + " ", + "This is a test group", + types.PermissionWrite, + ), + shouldErr: true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.group.Validate() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +func TestUserGroup_Update(t *testing.T) { + testCases := []struct { + name string + subspace types.UserGroup + update *types.GroupUpdate + expResult types.UserGroup + }{ + { + name: "nothing is updated when using DoNotModify", + subspace: types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + update: types.NewGroupUpdate( + types.DoNotModify, + types.DoNotModify, + ), + expResult: types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + }, + { + name: "each field is updated when edited", + subspace: types.NewUserGroup( + 1, + 1, + "Test group", + "This is a test group", + types.PermissionWrite, + ), + update: types.NewGroupUpdate( + "New group name", + "New group description", + ), + expResult: types.NewUserGroup( + 1, + 1, + "New group name", + "New group description", + types.PermissionWrite, + ), + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + result := tc.subspace.Update(tc.update) + require.Equal(t, tc.expResult, result) + }) + } +} diff --git a/x/subspaces/types/msgs.go b/x/subspaces/types/msgs.go new file mode 100644 index 0000000000..2233decfe6 --- /dev/null +++ b/x/subspaces/types/msgs.go @@ -0,0 +1,494 @@ +package types + +import ( + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// NewMsgCreateSubspace creates a new MsgCreateSubspace instance +func NewMsgCreateSubspace(name, description, treasury, owner, creator string) *MsgCreateSubspace { + if owner == "" { + // If the owner is empty, set the creator as the owner + owner = creator + } + + return &MsgCreateSubspace{ + Name: name, + Description: description, + Treasury: treasury, + Owner: owner, + Creator: creator, + } +} + +// Route implements sdk.Msg +func (msg MsgCreateSubspace) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgCreateSubspace) Type() string { return ActionCreateSubspace } + +// ValidateBasic implements sdk.Msg +func (msg MsgCreateSubspace) ValidateBasic() error { + if strings.TrimSpace(msg.Name) == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "subspace name cannot be empty or blank") + } + + if msg.Treasury != "" { + _, err := sdk.AccAddressFromBech32(msg.Treasury) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid treasury address") + } + } + + _, err := sdk.AccAddressFromBech32(msg.Owner) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid owner address") + } + + _, err = sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgCreateSubspace) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgCreateSubspace) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Creator) + return []sdk.AccAddress{addr} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewMsgEditSubspace creates a new MsgEditSubspace instance +func NewMsgEditSubspace(subspaceID uint64, name, description, treasury, owner, signer string) *MsgEditSubspace { + return &MsgEditSubspace{ + SubspaceID: subspaceID, + Name: name, + Description: description, + Treasury: treasury, + Owner: owner, + Signer: signer, + } +} + +// Route implements sdk.Msg +func (msg MsgEditSubspace) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgEditSubspace) Type() string { return ActionEditSubspace } + +// ValidateBasic implements sdk.Msg +func (msg MsgEditSubspace) ValidateBasic() error { + if msg.SubspaceID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + _, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgEditSubspace) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgEditSubspace) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Signer) + return []sdk.AccAddress{addr} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewMsgDeleteSubspace returns a new MsgDeleteSubspace instance +func NewMsgDeleteSubspace(subspaceID uint64, signer string) *MsgDeleteSubspace { + return &MsgDeleteSubspace{ + SubspaceID: subspaceID, + Signer: signer, + } +} + +// Route implements sdk.Msg +func (msg MsgDeleteSubspace) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgDeleteSubspace) Type() string { return ActionEditSubspace } + +// ValidateBasic implements sdk.Msg +func (msg MsgDeleteSubspace) ValidateBasic() error { + if msg.SubspaceID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + _, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgDeleteSubspace) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgDeleteSubspace) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Signer) + return []sdk.AccAddress{addr} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewMsgCreateUserGroup creates a new MsgCreateUserGroup instance +func NewMsgCreateUserGroup(subspaceID uint64, name, description string, permissions uint32, creator string) *MsgCreateUserGroup { + return &MsgCreateUserGroup{ + SubspaceID: subspaceID, + Name: name, + Description: description, + DefaultPermissions: permissions, + Creator: creator, + } +} + +// Route implements sdk.Msg +func (msg MsgCreateUserGroup) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgCreateUserGroup) Type() string { return ActionCreateUserGroup } + +// ValidateBasic implements sdk.Msg +func (msg MsgCreateUserGroup) ValidateBasic() error { + if msg.SubspaceID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + if strings.TrimSpace(msg.Name) == "" { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid group name: %s", msg.Name) + } + + _, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgCreateUserGroup) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgCreateUserGroup) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Creator) + return []sdk.AccAddress{addr} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewMsgEditUserGroup returns a new NewMsgEditUserGroup instance +func NewMsgEditUserGroup(subspaceID uint64, groupID uint32, name, description string, signer string) *MsgEditUserGroup { + return &MsgEditUserGroup{ + SubspaceID: subspaceID, + GroupID: groupID, + Name: name, + Description: description, + Signer: signer, + } +} + +// Route implements sdk.Msg +func (msg MsgEditUserGroup) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgEditUserGroup) Type() string { return ActionEditUserGroup } + +// ValidateBasic implements sdk.Msg +func (msg MsgEditUserGroup) ValidateBasic() error { + if msg.SubspaceID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + if msg.GroupID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid group id: %d", msg.GroupID) + } + + _, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgEditUserGroup) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgEditUserGroup) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Signer) + return []sdk.AccAddress{addr} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewMsgSetUserGroupPermissions returns a new MsgSetUserGroupPermissions instance +func NewMsgSetUserGroupPermissions(subspaceID uint64, groupID uint32, permissions Permission, signer string) *MsgSetUserGroupPermissions { + return &MsgSetUserGroupPermissions{ + SubspaceID: subspaceID, + GroupID: groupID, + Permissions: permissions, + Signer: signer, + } +} + +// Route implements sdk.Msg +func (msg MsgSetUserGroupPermissions) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgSetUserGroupPermissions) Type() string { return ActionSetUserGroupPermissions } + +// ValidateBasic implements sdk.Msg +func (msg MsgSetUserGroupPermissions) ValidateBasic() error { + if msg.SubspaceID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + if msg.GroupID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid group id: %d", msg.GroupID) + } + + _, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgSetUserGroupPermissions) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgSetUserGroupPermissions) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Signer) + return []sdk.AccAddress{addr} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewMsgDeleteUserGroup creates a new MsgDeleteUserGroup instance +func NewMsgDeleteUserGroup(subspaceID uint64, groupID uint32, signer string) *MsgDeleteUserGroup { + return &MsgDeleteUserGroup{ + SubspaceID: subspaceID, + GroupID: groupID, + Signer: signer, + } +} + +// Route implements sdk.Msg +func (msg MsgDeleteUserGroup) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgDeleteUserGroup) Type() string { return ActionDeleteUserGroup } + +// ValidateBasic implements sdk.Msg +func (msg MsgDeleteUserGroup) ValidateBasic() error { + if msg.SubspaceID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + if msg.GroupID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid group id: %d", msg.GroupID) + } + + _, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgDeleteUserGroup) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgDeleteUserGroup) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Signer) + return []sdk.AccAddress{addr} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewMsgAddUserToUserGroup creates a new MsgAddUserToUserGroup instance +func NewMsgAddUserToUserGroup(subspaceID uint64, groupID uint32, user string, signer string) *MsgAddUserToUserGroup { + return &MsgAddUserToUserGroup{ + SubspaceID: subspaceID, + GroupID: groupID, + User: user, + Signer: signer, + } +} + +// Route implements sdk.Msg +func (msg MsgAddUserToUserGroup) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgAddUserToUserGroup) Type() string { return ActionAddUserToUserGroup } + +// ValidateBasic implements sdk.Msg +func (msg MsgAddUserToUserGroup) ValidateBasic() error { + if msg.SubspaceID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + if msg.GroupID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid group id: %d", msg.GroupID) + } + + _, err := sdk.AccAddressFromBech32(msg.User) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid user address") + } + + _, err = sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgAddUserToUserGroup) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgAddUserToUserGroup) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Signer) + return []sdk.AccAddress{addr} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewMsgRemoveUserFromUserGroup creates a new MsgRemoveUserFromUserGroup instance +func NewMsgRemoveUserFromUserGroup(subspaceID uint64, groupID uint32, user string, signer string) *MsgRemoveUserFromUserGroup { + return &MsgRemoveUserFromUserGroup{ + SubspaceID: subspaceID, + GroupID: groupID, + User: user, + Signer: signer, + } +} + +// Route implements sdk.Msg +func (msg MsgRemoveUserFromUserGroup) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgRemoveUserFromUserGroup) Type() string { return ActionRemoveUserFromUserGroup } + +// ValidateBasic implements sdk.Msg +func (msg MsgRemoveUserFromUserGroup) ValidateBasic() error { + if msg.SubspaceID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + if msg.GroupID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid group id: %d", msg.GroupID) + } + + _, err := sdk.AccAddressFromBech32(msg.User) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid user address") + } + + _, err = sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgRemoveUserFromUserGroup) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgRemoveUserFromUserGroup) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Signer) + return []sdk.AccAddress{addr} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// NewMsgSetUserPermissions creates a new MsgSetUserPermissions instance +func NewMsgSetUserPermissions(subspaceID uint64, user string, permissions uint32, signer string) *MsgSetUserPermissions { + return &MsgSetUserPermissions{ + SubspaceID: subspaceID, + User: user, + Permissions: permissions, + Signer: signer, + } +} + +// Route implements sdk.Msg +func (msg MsgSetUserPermissions) Route() string { return RouterKey } + +// Type implements sdk.Msg +func (msg MsgSetUserPermissions) Type() string { return ActionSetUserPermissions } + +// ValidateBasic implements sdk.Msg +func (msg MsgSetUserPermissions) ValidateBasic() error { + if msg.SubspaceID == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + _, err := sdk.AccAddressFromBech32(msg.User) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid user address") + } + + _, err = sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + return nil +} + +// GetSignBytes implements sdk.Msg +func (msg MsgSetUserPermissions) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCodec.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgSetUserPermissions) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Signer) + return []sdk.AccAddress{addr} +} diff --git a/x/subspaces/types/msgs.pb.go b/x/subspaces/types/msgs.pb.go new file mode 100644 index 0000000000..80d4b2c816 --- /dev/null +++ b/x/subspaces/types/msgs.pb.go @@ -0,0 +1,4885 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/subspaces/v1/msgs.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgCreateSubspace represents the message used to create a subspace +type MsgCreateSubspace struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` + Treasury string `protobuf:"bytes,3,opt,name=treasury,proto3" json:"treasury,omitempty" yaml:"treasury"` + Owner string `protobuf:"bytes,4,opt,name=owner,proto3" json:"owner,omitempty" yaml:"owner"` + Creator string `protobuf:"bytes,5,opt,name=creator,proto3" json:"creator,omitempty" yaml:"creator"` +} + +func (m *MsgCreateSubspace) Reset() { *m = MsgCreateSubspace{} } +func (m *MsgCreateSubspace) String() string { return proto.CompactTextString(m) } +func (*MsgCreateSubspace) ProtoMessage() {} +func (*MsgCreateSubspace) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{0} +} +func (m *MsgCreateSubspace) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateSubspace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateSubspace.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateSubspace) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateSubspace.Merge(m, src) +} +func (m *MsgCreateSubspace) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateSubspace) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateSubspace.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateSubspace proto.InternalMessageInfo + +// MsgCreateSubspaceResponse defines the Msg/CreateSubspace response type +type MsgCreateSubspaceResponse struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` +} + +func (m *MsgCreateSubspaceResponse) Reset() { *m = MsgCreateSubspaceResponse{} } +func (m *MsgCreateSubspaceResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateSubspaceResponse) ProtoMessage() {} +func (*MsgCreateSubspaceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{1} +} +func (m *MsgCreateSubspaceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateSubspaceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateSubspaceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateSubspaceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateSubspaceResponse.Merge(m, src) +} +func (m *MsgCreateSubspaceResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateSubspaceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateSubspaceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateSubspaceResponse proto.InternalMessageInfo + +func (m *MsgCreateSubspaceResponse) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +// MsgEditSubspace represents the message used to edit a subspace fields +type MsgEditSubspace struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` + Treasury string `protobuf:"bytes,4,opt,name=treasury,proto3" json:"treasury,omitempty" yaml:"treasury"` + Owner string `protobuf:"bytes,5,opt,name=owner,proto3" json:"owner,omitempty" yaml:"owner"` + Signer string `protobuf:"bytes,6,opt,name=signer,proto3" json:"signer,omitempty" yaml:"signer"` +} + +func (m *MsgEditSubspace) Reset() { *m = MsgEditSubspace{} } +func (m *MsgEditSubspace) String() string { return proto.CompactTextString(m) } +func (*MsgEditSubspace) ProtoMessage() {} +func (*MsgEditSubspace) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{2} +} +func (m *MsgEditSubspace) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgEditSubspace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgEditSubspace.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgEditSubspace) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgEditSubspace.Merge(m, src) +} +func (m *MsgEditSubspace) XXX_Size() int { + return m.Size() +} +func (m *MsgEditSubspace) XXX_DiscardUnknown() { + xxx_messageInfo_MsgEditSubspace.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgEditSubspace proto.InternalMessageInfo + +// MsgEditSubspaceResponse defines the Msg/EditSubspace response type +type MsgEditSubspaceResponse struct { +} + +func (m *MsgEditSubspaceResponse) Reset() { *m = MsgEditSubspaceResponse{} } +func (m *MsgEditSubspaceResponse) String() string { return proto.CompactTextString(m) } +func (*MsgEditSubspaceResponse) ProtoMessage() {} +func (*MsgEditSubspaceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{3} +} +func (m *MsgEditSubspaceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgEditSubspaceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgEditSubspaceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgEditSubspaceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgEditSubspaceResponse.Merge(m, src) +} +func (m *MsgEditSubspaceResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgEditSubspaceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgEditSubspaceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgEditSubspaceResponse proto.InternalMessageInfo + +// MsgDeleteSubspace represents the message used to delete a subspace +type MsgDeleteSubspace struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + Signer string `protobuf:"bytes,2,opt,name=signer,proto3" json:"signer,omitempty" yaml:"signer"` +} + +func (m *MsgDeleteSubspace) Reset() { *m = MsgDeleteSubspace{} } +func (m *MsgDeleteSubspace) String() string { return proto.CompactTextString(m) } +func (*MsgDeleteSubspace) ProtoMessage() {} +func (*MsgDeleteSubspace) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{4} +} +func (m *MsgDeleteSubspace) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDeleteSubspace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDeleteSubspace.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgDeleteSubspace) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDeleteSubspace.Merge(m, src) +} +func (m *MsgDeleteSubspace) XXX_Size() int { + return m.Size() +} +func (m *MsgDeleteSubspace) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDeleteSubspace.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDeleteSubspace proto.InternalMessageInfo + +// MsgDeleteSubspaceResponse defines the Msg/DeleteSubspace response type +type MsgDeleteSubspaceResponse struct { +} + +func (m *MsgDeleteSubspaceResponse) Reset() { *m = MsgDeleteSubspaceResponse{} } +func (m *MsgDeleteSubspaceResponse) String() string { return proto.CompactTextString(m) } +func (*MsgDeleteSubspaceResponse) ProtoMessage() {} +func (*MsgDeleteSubspaceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{5} +} +func (m *MsgDeleteSubspaceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDeleteSubspaceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDeleteSubspaceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgDeleteSubspaceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDeleteSubspaceResponse.Merge(m, src) +} +func (m *MsgDeleteSubspaceResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgDeleteSubspaceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDeleteSubspaceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDeleteSubspaceResponse proto.InternalMessageInfo + +// MsgCreateUserGroup represents the message used to create a user group +type MsgCreateUserGroup struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + // Name of the group + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` + // Optional description of the group + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` + // Default permissions to be applied to the group + DefaultPermissions uint32 `protobuf:"varint,4,opt,name=default_permissions,json=defaultPermissions,proto3" json:"default_permissions,omitempty" yaml:"default_permissions"` + // Creator of the group + Creator string `protobuf:"bytes,5,opt,name=creator,proto3" json:"creator,omitempty" yaml:"creator"` +} + +func (m *MsgCreateUserGroup) Reset() { *m = MsgCreateUserGroup{} } +func (m *MsgCreateUserGroup) String() string { return proto.CompactTextString(m) } +func (*MsgCreateUserGroup) ProtoMessage() {} +func (*MsgCreateUserGroup) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{6} +} +func (m *MsgCreateUserGroup) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateUserGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateUserGroup.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateUserGroup) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateUserGroup.Merge(m, src) +} +func (m *MsgCreateUserGroup) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateUserGroup) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateUserGroup.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateUserGroup proto.InternalMessageInfo + +func (m *MsgCreateUserGroup) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgCreateUserGroup) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *MsgCreateUserGroup) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *MsgCreateUserGroup) GetDefaultPermissions() uint32 { + if m != nil { + return m.DefaultPermissions + } + return 0 +} + +func (m *MsgCreateUserGroup) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +// MsgCreateUserGroupResponse defines the Msg/CreateUserGroup response type +type MsgCreateUserGroupResponse struct { + GroupID uint32 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty" yaml:"group_id"` +} + +func (m *MsgCreateUserGroupResponse) Reset() { *m = MsgCreateUserGroupResponse{} } +func (m *MsgCreateUserGroupResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateUserGroupResponse) ProtoMessage() {} +func (*MsgCreateUserGroupResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{7} +} +func (m *MsgCreateUserGroupResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateUserGroupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateUserGroupResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateUserGroupResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateUserGroupResponse.Merge(m, src) +} +func (m *MsgCreateUserGroupResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateUserGroupResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateUserGroupResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateUserGroupResponse proto.InternalMessageInfo + +func (m *MsgCreateUserGroupResponse) GetGroupID() uint32 { + if m != nil { + return m.GroupID + } + return 0 +} + +// MsgEditUserGroup represents the message used to edit a user group +type MsgEditUserGroup struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + GroupID uint32 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty" yaml:"group_id"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` + Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` + Signer string `protobuf:"bytes,5,opt,name=signer,proto3" json:"signer,omitempty" yaml:"signer"` +} + +func (m *MsgEditUserGroup) Reset() { *m = MsgEditUserGroup{} } +func (m *MsgEditUserGroup) String() string { return proto.CompactTextString(m) } +func (*MsgEditUserGroup) ProtoMessage() {} +func (*MsgEditUserGroup) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{8} +} +func (m *MsgEditUserGroup) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgEditUserGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgEditUserGroup.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgEditUserGroup) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgEditUserGroup.Merge(m, src) +} +func (m *MsgEditUserGroup) XXX_Size() int { + return m.Size() +} +func (m *MsgEditUserGroup) XXX_DiscardUnknown() { + xxx_messageInfo_MsgEditUserGroup.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgEditUserGroup proto.InternalMessageInfo + +func (m *MsgEditUserGroup) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgEditUserGroup) GetGroupID() uint32 { + if m != nil { + return m.GroupID + } + return 0 +} + +func (m *MsgEditUserGroup) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *MsgEditUserGroup) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *MsgEditUserGroup) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +// MsgEditUserGroupResponse defines the Msg/EditUserGroup response type +type MsgEditUserGroupResponse struct { +} + +func (m *MsgEditUserGroupResponse) Reset() { *m = MsgEditUserGroupResponse{} } +func (m *MsgEditUserGroupResponse) String() string { return proto.CompactTextString(m) } +func (*MsgEditUserGroupResponse) ProtoMessage() {} +func (*MsgEditUserGroupResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{9} +} +func (m *MsgEditUserGroupResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgEditUserGroupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgEditUserGroupResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgEditUserGroupResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgEditUserGroupResponse.Merge(m, src) +} +func (m *MsgEditUserGroupResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgEditUserGroupResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgEditUserGroupResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgEditUserGroupResponse proto.InternalMessageInfo + +// MsgSetUserGroupPermissions represents the message used to set the permissions +// of a user group +type MsgSetUserGroupPermissions struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + GroupID uint32 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty" yaml:"group_id"` + Permissions uint32 `protobuf:"varint,3,opt,name=permissions,proto3" json:"permissions,omitempty" yaml:"permissions"` + Signer string `protobuf:"bytes,4,opt,name=signer,proto3" json:"signer,omitempty" yaml:"signer"` +} + +func (m *MsgSetUserGroupPermissions) Reset() { *m = MsgSetUserGroupPermissions{} } +func (m *MsgSetUserGroupPermissions) String() string { return proto.CompactTextString(m) } +func (*MsgSetUserGroupPermissions) ProtoMessage() {} +func (*MsgSetUserGroupPermissions) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{10} +} +func (m *MsgSetUserGroupPermissions) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetUserGroupPermissions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetUserGroupPermissions.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgSetUserGroupPermissions) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetUserGroupPermissions.Merge(m, src) +} +func (m *MsgSetUserGroupPermissions) XXX_Size() int { + return m.Size() +} +func (m *MsgSetUserGroupPermissions) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetUserGroupPermissions.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetUserGroupPermissions proto.InternalMessageInfo + +func (m *MsgSetUserGroupPermissions) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgSetUserGroupPermissions) GetGroupID() uint32 { + if m != nil { + return m.GroupID + } + return 0 +} + +func (m *MsgSetUserGroupPermissions) GetPermissions() uint32 { + if m != nil { + return m.Permissions + } + return 0 +} + +func (m *MsgSetUserGroupPermissions) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +// MsgSetUserGroupPermissionsResponse defines the +// Msg/SetUserGroupPermissionsResponse response type +type MsgSetUserGroupPermissionsResponse struct { +} + +func (m *MsgSetUserGroupPermissionsResponse) Reset() { *m = MsgSetUserGroupPermissionsResponse{} } +func (m *MsgSetUserGroupPermissionsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSetUserGroupPermissionsResponse) ProtoMessage() {} +func (*MsgSetUserGroupPermissionsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{11} +} +func (m *MsgSetUserGroupPermissionsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetUserGroupPermissionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetUserGroupPermissionsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgSetUserGroupPermissionsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetUserGroupPermissionsResponse.Merge(m, src) +} +func (m *MsgSetUserGroupPermissionsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSetUserGroupPermissionsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetUserGroupPermissionsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetUserGroupPermissionsResponse proto.InternalMessageInfo + +// MsgDeleteUserGroup represents the message used to delete a user group +type MsgDeleteUserGroup struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + GroupID uint32 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty" yaml:"group_id"` + Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty" yaml:"signer"` +} + +func (m *MsgDeleteUserGroup) Reset() { *m = MsgDeleteUserGroup{} } +func (m *MsgDeleteUserGroup) String() string { return proto.CompactTextString(m) } +func (*MsgDeleteUserGroup) ProtoMessage() {} +func (*MsgDeleteUserGroup) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{12} +} +func (m *MsgDeleteUserGroup) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDeleteUserGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDeleteUserGroup.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgDeleteUserGroup) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDeleteUserGroup.Merge(m, src) +} +func (m *MsgDeleteUserGroup) XXX_Size() int { + return m.Size() +} +func (m *MsgDeleteUserGroup) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDeleteUserGroup.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDeleteUserGroup proto.InternalMessageInfo + +func (m *MsgDeleteUserGroup) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgDeleteUserGroup) GetGroupID() uint32 { + if m != nil { + return m.GroupID + } + return 0 +} + +func (m *MsgDeleteUserGroup) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +// MsgDeleteUserGroupResponse defines the Msg/DeleteUserGroup response type +type MsgDeleteUserGroupResponse struct { +} + +func (m *MsgDeleteUserGroupResponse) Reset() { *m = MsgDeleteUserGroupResponse{} } +func (m *MsgDeleteUserGroupResponse) String() string { return proto.CompactTextString(m) } +func (*MsgDeleteUserGroupResponse) ProtoMessage() {} +func (*MsgDeleteUserGroupResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{13} +} +func (m *MsgDeleteUserGroupResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDeleteUserGroupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDeleteUserGroupResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgDeleteUserGroupResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDeleteUserGroupResponse.Merge(m, src) +} +func (m *MsgDeleteUserGroupResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgDeleteUserGroupResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDeleteUserGroupResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDeleteUserGroupResponse proto.InternalMessageInfo + +// MsgAddUserToUserGroup represents the message used to add a user to a user +// group +type MsgAddUserToUserGroup struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + GroupID uint32 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty" yaml:"group_id"` + User string `protobuf:"bytes,3,opt,name=user,proto3" json:"user,omitempty" yaml:"user"` + Signer string `protobuf:"bytes,4,opt,name=signer,proto3" json:"signer,omitempty" yaml:"signer"` +} + +func (m *MsgAddUserToUserGroup) Reset() { *m = MsgAddUserToUserGroup{} } +func (m *MsgAddUserToUserGroup) String() string { return proto.CompactTextString(m) } +func (*MsgAddUserToUserGroup) ProtoMessage() {} +func (*MsgAddUserToUserGroup) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{14} +} +func (m *MsgAddUserToUserGroup) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAddUserToUserGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAddUserToUserGroup.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgAddUserToUserGroup) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAddUserToUserGroup.Merge(m, src) +} +func (m *MsgAddUserToUserGroup) XXX_Size() int { + return m.Size() +} +func (m *MsgAddUserToUserGroup) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAddUserToUserGroup.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAddUserToUserGroup proto.InternalMessageInfo + +func (m *MsgAddUserToUserGroup) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgAddUserToUserGroup) GetGroupID() uint32 { + if m != nil { + return m.GroupID + } + return 0 +} + +func (m *MsgAddUserToUserGroup) GetUser() string { + if m != nil { + return m.User + } + return "" +} + +func (m *MsgAddUserToUserGroup) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +// MsgAddUserToUserGroupResponse defines the Msg/AddUserToUserGroupResponse +// response type +type MsgAddUserToUserGroupResponse struct { +} + +func (m *MsgAddUserToUserGroupResponse) Reset() { *m = MsgAddUserToUserGroupResponse{} } +func (m *MsgAddUserToUserGroupResponse) String() string { return proto.CompactTextString(m) } +func (*MsgAddUserToUserGroupResponse) ProtoMessage() {} +func (*MsgAddUserToUserGroupResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{15} +} +func (m *MsgAddUserToUserGroupResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAddUserToUserGroupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAddUserToUserGroupResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgAddUserToUserGroupResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAddUserToUserGroupResponse.Merge(m, src) +} +func (m *MsgAddUserToUserGroupResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgAddUserToUserGroupResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAddUserToUserGroupResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAddUserToUserGroupResponse proto.InternalMessageInfo + +// MsgRemoveUserFromUserGroup represents the message used to remove a user from +// a user group +type MsgRemoveUserFromUserGroup struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + GroupID uint32 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty" yaml:"group_id"` + User string `protobuf:"bytes,3,opt,name=user,proto3" json:"user,omitempty" yaml:"user"` + Signer string `protobuf:"bytes,4,opt,name=signer,proto3" json:"signer,omitempty" yaml:"signer"` +} + +func (m *MsgRemoveUserFromUserGroup) Reset() { *m = MsgRemoveUserFromUserGroup{} } +func (m *MsgRemoveUserFromUserGroup) String() string { return proto.CompactTextString(m) } +func (*MsgRemoveUserFromUserGroup) ProtoMessage() {} +func (*MsgRemoveUserFromUserGroup) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{16} +} +func (m *MsgRemoveUserFromUserGroup) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRemoveUserFromUserGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRemoveUserFromUserGroup.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgRemoveUserFromUserGroup) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRemoveUserFromUserGroup.Merge(m, src) +} +func (m *MsgRemoveUserFromUserGroup) XXX_Size() int { + return m.Size() +} +func (m *MsgRemoveUserFromUserGroup) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRemoveUserFromUserGroup.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRemoveUserFromUserGroup proto.InternalMessageInfo + +func (m *MsgRemoveUserFromUserGroup) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgRemoveUserFromUserGroup) GetGroupID() uint32 { + if m != nil { + return m.GroupID + } + return 0 +} + +func (m *MsgRemoveUserFromUserGroup) GetUser() string { + if m != nil { + return m.User + } + return "" +} + +func (m *MsgRemoveUserFromUserGroup) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +// MsgRemoveUserFromUserGroupResponse defines the +// Msg/RemoveUserFromUserGroupResponse response type +type MsgRemoveUserFromUserGroupResponse struct { +} + +func (m *MsgRemoveUserFromUserGroupResponse) Reset() { *m = MsgRemoveUserFromUserGroupResponse{} } +func (m *MsgRemoveUserFromUserGroupResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRemoveUserFromUserGroupResponse) ProtoMessage() {} +func (*MsgRemoveUserFromUserGroupResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{17} +} +func (m *MsgRemoveUserFromUserGroupResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRemoveUserFromUserGroupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRemoveUserFromUserGroupResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgRemoveUserFromUserGroupResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRemoveUserFromUserGroupResponse.Merge(m, src) +} +func (m *MsgRemoveUserFromUserGroupResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRemoveUserFromUserGroupResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRemoveUserFromUserGroupResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRemoveUserFromUserGroupResponse proto.InternalMessageInfo + +// MsgSetUserPermissions represents the message used to set the permissions of a +// specific user +type MsgSetUserPermissions struct { + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + User string `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty" yaml:"user"` + Permissions uint32 `protobuf:"varint,3,opt,name=permissions,proto3" json:"permissions,omitempty" yaml:"permissions"` + Signer string `protobuf:"bytes,4,opt,name=signer,proto3" json:"signer,omitempty" yaml:"signer"` +} + +func (m *MsgSetUserPermissions) Reset() { *m = MsgSetUserPermissions{} } +func (m *MsgSetUserPermissions) String() string { return proto.CompactTextString(m) } +func (*MsgSetUserPermissions) ProtoMessage() {} +func (*MsgSetUserPermissions) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{18} +} +func (m *MsgSetUserPermissions) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetUserPermissions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetUserPermissions.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgSetUserPermissions) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetUserPermissions.Merge(m, src) +} +func (m *MsgSetUserPermissions) XXX_Size() int { + return m.Size() +} +func (m *MsgSetUserPermissions) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetUserPermissions.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetUserPermissions proto.InternalMessageInfo + +func (m *MsgSetUserPermissions) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgSetUserPermissions) GetUser() string { + if m != nil { + return m.User + } + return "" +} + +func (m *MsgSetUserPermissions) GetPermissions() uint32 { + if m != nil { + return m.Permissions + } + return 0 +} + +func (m *MsgSetUserPermissions) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +// MsgSetUserPermissionsResponse defines the Msg/SetPermissionsResponse +// response type +type MsgSetUserPermissionsResponse struct { +} + +func (m *MsgSetUserPermissionsResponse) Reset() { *m = MsgSetUserPermissionsResponse{} } +func (m *MsgSetUserPermissionsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSetUserPermissionsResponse) ProtoMessage() {} +func (*MsgSetUserPermissionsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c16a431ff9a3b35b, []int{19} +} +func (m *MsgSetUserPermissionsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetUserPermissionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetUserPermissionsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgSetUserPermissionsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetUserPermissionsResponse.Merge(m, src) +} +func (m *MsgSetUserPermissionsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSetUserPermissionsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetUserPermissionsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetUserPermissionsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgCreateSubspace)(nil), "desmos.subspaces.v1.MsgCreateSubspace") + proto.RegisterType((*MsgCreateSubspaceResponse)(nil), "desmos.subspaces.v1.MsgCreateSubspaceResponse") + proto.RegisterType((*MsgEditSubspace)(nil), "desmos.subspaces.v1.MsgEditSubspace") + proto.RegisterType((*MsgEditSubspaceResponse)(nil), "desmos.subspaces.v1.MsgEditSubspaceResponse") + proto.RegisterType((*MsgDeleteSubspace)(nil), "desmos.subspaces.v1.MsgDeleteSubspace") + proto.RegisterType((*MsgDeleteSubspaceResponse)(nil), "desmos.subspaces.v1.MsgDeleteSubspaceResponse") + proto.RegisterType((*MsgCreateUserGroup)(nil), "desmos.subspaces.v1.MsgCreateUserGroup") + proto.RegisterType((*MsgCreateUserGroupResponse)(nil), "desmos.subspaces.v1.MsgCreateUserGroupResponse") + proto.RegisterType((*MsgEditUserGroup)(nil), "desmos.subspaces.v1.MsgEditUserGroup") + proto.RegisterType((*MsgEditUserGroupResponse)(nil), "desmos.subspaces.v1.MsgEditUserGroupResponse") + proto.RegisterType((*MsgSetUserGroupPermissions)(nil), "desmos.subspaces.v1.MsgSetUserGroupPermissions") + proto.RegisterType((*MsgSetUserGroupPermissionsResponse)(nil), "desmos.subspaces.v1.MsgSetUserGroupPermissionsResponse") + proto.RegisterType((*MsgDeleteUserGroup)(nil), "desmos.subspaces.v1.MsgDeleteUserGroup") + proto.RegisterType((*MsgDeleteUserGroupResponse)(nil), "desmos.subspaces.v1.MsgDeleteUserGroupResponse") + proto.RegisterType((*MsgAddUserToUserGroup)(nil), "desmos.subspaces.v1.MsgAddUserToUserGroup") + proto.RegisterType((*MsgAddUserToUserGroupResponse)(nil), "desmos.subspaces.v1.MsgAddUserToUserGroupResponse") + proto.RegisterType((*MsgRemoveUserFromUserGroup)(nil), "desmos.subspaces.v1.MsgRemoveUserFromUserGroup") + proto.RegisterType((*MsgRemoveUserFromUserGroupResponse)(nil), "desmos.subspaces.v1.MsgRemoveUserFromUserGroupResponse") + proto.RegisterType((*MsgSetUserPermissions)(nil), "desmos.subspaces.v1.MsgSetUserPermissions") + proto.RegisterType((*MsgSetUserPermissionsResponse)(nil), "desmos.subspaces.v1.MsgSetUserPermissionsResponse") +} + +func init() { proto.RegisterFile("desmos/subspaces/v1/msgs.proto", fileDescriptor_c16a431ff9a3b35b) } + +var fileDescriptor_c16a431ff9a3b35b = []byte{ + // 920 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0x4b, 0x6f, 0xe3, 0x44, + 0x1c, 0x8f, 0x9d, 0xa4, 0x0d, 0xff, 0x6c, 0x9a, 0x5d, 0x17, 0xd8, 0xac, 0x01, 0x7b, 0x35, 0x94, + 0x5d, 0x58, 0xed, 0xc6, 0xda, 0x70, 0x60, 0xd9, 0x1b, 0x61, 0x0b, 0xaa, 0x44, 0x04, 0x72, 0x41, + 0x48, 0x5c, 0xaa, 0x24, 0x1e, 0x5c, 0x8b, 0x38, 0x13, 0x79, 0x9c, 0x40, 0xcf, 0xbd, 0x70, 0x83, + 0x4f, 0x80, 0xfa, 0x35, 0x38, 0x72, 0x40, 0xe2, 0xd8, 0x23, 0x27, 0x0b, 0xa5, 0x97, 0x72, 0xe1, + 0x90, 0x03, 0x67, 0xe4, 0xb1, 0x3d, 0x99, 0x3c, 0x9c, 0x38, 0xa8, 0x40, 0xd9, 0x9b, 0x33, 0xff, + 0xdf, 0x3c, 0x7e, 0x8f, 0x79, 0x28, 0xa0, 0x59, 0x98, 0xba, 0x84, 0x1a, 0x74, 0xd8, 0xa1, 0x83, + 0x76, 0x17, 0x53, 0x63, 0xf4, 0xd8, 0x70, 0xa9, 0x4d, 0xeb, 0x03, 0x8f, 0xf8, 0x44, 0xd9, 0x8d, + 0xea, 0x75, 0x5e, 0xaf, 0x8f, 0x1e, 0xab, 0x2f, 0xda, 0xc4, 0x26, 0xac, 0x6e, 0x84, 0x5f, 0x11, + 0x54, 0xbd, 0xbb, 0x74, 0x28, 0x62, 0xe1, 0x5e, 0x3c, 0x18, 0x3a, 0x95, 0xe1, 0x56, 0x8b, 0xda, + 0xef, 0x7b, 0xb8, 0xed, 0xe3, 0xc3, 0x18, 0xa6, 0xbc, 0x0e, 0x85, 0x7e, 0xdb, 0xc5, 0x35, 0xe9, + 0xae, 0xf4, 0xe6, 0x0b, 0xcd, 0xea, 0x24, 0xd0, 0xcb, 0x27, 0x6d, 0xb7, 0xf7, 0x14, 0x85, 0xad, + 0xc8, 0x64, 0x45, 0xe5, 0x09, 0x94, 0x2d, 0x4c, 0xbb, 0x9e, 0x33, 0xf0, 0x1d, 0xd2, 0xaf, 0xc9, + 0x0c, 0xfb, 0xf2, 0x24, 0xd0, 0x95, 0x08, 0x2b, 0x14, 0x91, 0x29, 0x42, 0x15, 0x03, 0x4a, 0xbe, + 0x87, 0xdb, 0x74, 0xe8, 0x9d, 0xd4, 0xf2, 0xac, 0xdb, 0xee, 0x24, 0xd0, 0xab, 0x51, 0xb7, 0xa4, + 0x82, 0x4c, 0x0e, 0x52, 0xee, 0x41, 0x91, 0x7c, 0xdd, 0xc7, 0x5e, 0xad, 0xc0, 0xd0, 0x37, 0x27, + 0x81, 0x7e, 0x23, 0x42, 0xb3, 0x66, 0x64, 0x46, 0x65, 0xe5, 0x21, 0x6c, 0x77, 0x43, 0x26, 0xc4, + 0xab, 0x15, 0x19, 0x52, 0x99, 0x04, 0xfa, 0x4e, 0x84, 0x8c, 0x0b, 0xc8, 0x4c, 0x20, 0x4f, 0x4b, + 0xdf, 0x9e, 0xe9, 0xb9, 0xcb, 0x33, 0x3d, 0x87, 0x3a, 0x70, 0x67, 0x41, 0x04, 0x13, 0xd3, 0x01, + 0xe9, 0x53, 0xac, 0xec, 0x43, 0x39, 0xd1, 0xef, 0xc8, 0xb1, 0x98, 0x26, 0x85, 0xe6, 0xde, 0x38, + 0xd0, 0x21, 0x81, 0x1e, 0x3c, 0x9b, 0xb2, 0x16, 0xa0, 0xc8, 0x84, 0xe4, 0xd7, 0x81, 0x85, 0x7e, + 0x96, 0xa1, 0xda, 0xa2, 0xf6, 0xbe, 0xe5, 0xf8, 0x5c, 0xe7, 0xab, 0x19, 0x9a, 0xdb, 0x25, 0x6f, + 0x60, 0x57, 0xfe, 0xef, 0xd9, 0x55, 0xd8, 0xc8, 0xae, 0xe2, 0x6a, 0xbb, 0xde, 0x82, 0x2d, 0xea, + 0xd8, 0x21, 0x70, 0x8b, 0x01, 0x6f, 0x4d, 0x02, 0xbd, 0x12, 0x73, 0x65, 0xed, 0xc8, 0x8c, 0x01, + 0x82, 0x57, 0x77, 0xe0, 0xf6, 0x9c, 0x8c, 0x89, 0x53, 0xe8, 0x3b, 0x89, 0x85, 0xf9, 0x19, 0xee, + 0x61, 0x21, 0xcc, 0x57, 0x24, 0xf2, 0x74, 0xb1, 0x72, 0xf6, 0xc5, 0xbe, 0xc2, 0x82, 0x35, 0xbb, + 0x20, 0xbe, 0xdc, 0x1f, 0x65, 0x50, 0x78, 0xec, 0x3e, 0xa3, 0xd8, 0xfb, 0xd0, 0x23, 0xc3, 0xc1, + 0xff, 0x24, 0x14, 0x1f, 0xc3, 0xae, 0x85, 0xbf, 0x6c, 0x0f, 0x7b, 0xfe, 0xd1, 0x00, 0x7b, 0xae, + 0x43, 0xa9, 0x43, 0xfa, 0x94, 0xe5, 0xa3, 0xd2, 0xd4, 0x26, 0x81, 0xae, 0x26, 0x23, 0x2c, 0x80, + 0x90, 0xa9, 0xc4, 0xad, 0x9f, 0x4c, 0x1b, 0x37, 0xdb, 0xbb, 0xe8, 0x73, 0x50, 0x17, 0xa5, 0xe3, + 0x5b, 0xf6, 0x5d, 0x28, 0xd9, 0x61, 0x43, 0xa2, 0x5f, 0xa5, 0xa9, 0x8d, 0x03, 0x7d, 0x9b, 0x81, + 0x98, 0x78, 0x71, 0x78, 0x13, 0x10, 0x32, 0xb7, 0xd9, 0xe7, 0x81, 0x85, 0x7e, 0x90, 0xe1, 0x66, + 0x9c, 0xaf, 0x2b, 0xb7, 0x44, 0x5c, 0x96, 0xbc, 0xd1, 0xb2, 0xb8, 0x9b, 0xf9, 0x0d, 0xdc, 0x2c, + 0x64, 0x77, 0x73, 0x1a, 0xee, 0xe2, 0x9a, 0x70, 0x23, 0x15, 0x6a, 0xf3, 0xfa, 0xf0, 0x44, 0x9f, + 0xca, 0xcc, 0x96, 0x43, 0x3c, 0xad, 0x89, 0x16, 0xff, 0xf7, 0x32, 0x3e, 0x81, 0xb2, 0x98, 0xd6, + 0x3c, 0xeb, 0x2d, 0x28, 0x34, 0x93, 0x52, 0x11, 0x2a, 0x28, 0x54, 0x58, 0xa7, 0xd0, 0x1e, 0xa0, + 0x74, 0x11, 0xb8, 0x56, 0x3f, 0x49, 0x6c, 0xf7, 0x47, 0x67, 0xc3, 0x75, 0x8a, 0xda, 0x94, 0x69, + 0x7e, 0x1d, 0xd3, 0x57, 0x99, 0xdd, 0x73, 0x14, 0x38, 0xc3, 0xdf, 0x25, 0x78, 0xa9, 0x45, 0xed, + 0xf7, 0x2c, 0x2b, 0xac, 0x7d, 0x4a, 0xae, 0xd9, 0x7e, 0x1a, 0x52, 0x4e, 0x51, 0xd8, 0x4f, 0x61, + 0x2b, 0x32, 0x59, 0x71, 0x13, 0xcf, 0x75, 0x78, 0x6d, 0x29, 0x55, 0x2e, 0xc6, 0x1f, 0x12, 0xd3, + 0xca, 0xc4, 0x2e, 0x19, 0x31, 0xad, 0x3e, 0xf0, 0x88, 0xfb, 0x3c, 0x2b, 0x12, 0xed, 0x82, 0x14, + 0xbe, 0x5c, 0x96, 0xcb, 0x28, 0x23, 0xf1, 0x66, 0xf9, 0x07, 0x0e, 0x8b, 0x84, 0x96, 0xbc, 0x8a, + 0xd6, 0xbf, 0x72, 0x2c, 0x44, 0x11, 0x59, 0x64, 0x9a, 0x68, 0xd1, 0xf8, 0xb3, 0x04, 0xf9, 0x16, + 0xb5, 0x95, 0x63, 0xd8, 0x99, 0x7b, 0x8f, 0xdf, 0xab, 0x2f, 0x79, 0xf3, 0xd7, 0x17, 0x9e, 0xac, + 0x6a, 0x3d, 0x1b, 0x8e, 0xdf, 0x93, 0x1d, 0xb8, 0x31, 0xf3, 0x1e, 0xdd, 0x4b, 0xeb, 0x2f, 0xa2, + 0xd4, 0x87, 0x59, 0x50, 0x7c, 0x8e, 0x63, 0xd8, 0x99, 0x7b, 0x90, 0xa5, 0xb2, 0x99, 0xc5, 0xa5, + 0xb3, 0x59, 0xfe, 0x9e, 0x52, 0xbe, 0x82, 0xea, 0xfc, 0x5b, 0xea, 0xfe, 0x6a, 0x41, 0x38, 0x50, + 0x35, 0x32, 0x02, 0xf9, 0x64, 0x18, 0x2a, 0xb3, 0x6f, 0x84, 0x37, 0x56, 0xa9, 0x32, 0x9d, 0xe8, + 0x51, 0x26, 0x18, 0x9f, 0xe6, 0x54, 0x82, 0xdb, 0x69, 0xd7, 0x69, 0xea, 0x9a, 0x53, 0x3a, 0xa8, + 0xef, 0x6c, 0xd8, 0x41, 0x54, 0x76, 0xfe, 0x9e, 0xba, 0xbf, 0xda, 0x9c, 0x0c, 0xca, 0xa6, 0x5c, + 0x1b, 0x8a, 0x0f, 0xca, 0x92, 0x2b, 0xe3, 0x41, 0xda, 0x30, 0x8b, 0x58, 0xb5, 0x91, 0x1d, 0x3b, + 0x23, 0x74, 0xda, 0xe1, 0x9c, 0x4a, 0x21, 0xa5, 0x43, 0xba, 0xd0, 0x6b, 0x8e, 0xc3, 0x90, 0xfb, + 0x92, 0xa3, 0xf0, 0xc1, 0x1a, 0xdf, 0x44, 0x8f, 0x1b, 0xd9, 0xb1, 0xc9, 0xac, 0xcd, 0x8f, 0x7e, + 0x19, 0x6b, 0xd2, 0xf9, 0x58, 0x93, 0x7e, 0x1b, 0x6b, 0xd2, 0xf7, 0x17, 0x5a, 0xee, 0xfc, 0x42, + 0xcb, 0xfd, 0x7a, 0xa1, 0xe5, 0xbe, 0x68, 0xd8, 0x8e, 0x7f, 0x3c, 0xec, 0xd4, 0xbb, 0xc4, 0x35, + 0xa2, 0x71, 0x1f, 0xf5, 0xda, 0x1d, 0x1a, 0x7f, 0x1b, 0xa3, 0x86, 0xf1, 0x8d, 0xf0, 0xe7, 0x82, + 0x7f, 0x32, 0xc0, 0xb4, 0xb3, 0xc5, 0xfe, 0x59, 0x78, 0xfb, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x46, 0x65, 0xcc, 0x53, 0xc8, 0x10, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // CreateSubspace allows to create a subspace + CreateSubspace(ctx context.Context, in *MsgCreateSubspace, opts ...grpc.CallOption) (*MsgCreateSubspaceResponse, error) + // EditSubspace allows to edit a subspace + EditSubspace(ctx context.Context, in *MsgEditSubspace, opts ...grpc.CallOption) (*MsgEditSubspaceResponse, error) + // DeleteSubspace allows to delete a subspace + DeleteSubspace(ctx context.Context, in *MsgDeleteSubspace, opts ...grpc.CallOption) (*MsgDeleteSubspaceResponse, error) + // CreateUserGroup allows to create a user group + CreateUserGroup(ctx context.Context, in *MsgCreateUserGroup, opts ...grpc.CallOption) (*MsgCreateUserGroupResponse, error) + // EditUserGroup allows to edit a user group + EditUserGroup(ctx context.Context, in *MsgEditUserGroup, opts ...grpc.CallOption) (*MsgEditUserGroupResponse, error) + // SetUserGroupPermissions allows to set the permissions for a specific group + SetUserGroupPermissions(ctx context.Context, in *MsgSetUserGroupPermissions, opts ...grpc.CallOption) (*MsgSetUserGroupPermissionsResponse, error) + // DeleteUserGroup allows to delete an existing user group + DeleteUserGroup(ctx context.Context, in *MsgDeleteUserGroup, opts ...grpc.CallOption) (*MsgDeleteUserGroupResponse, error) + // AddUserToUserGroup allows to add a specific user to a specific user group + AddUserToUserGroup(ctx context.Context, in *MsgAddUserToUserGroup, opts ...grpc.CallOption) (*MsgAddUserToUserGroupResponse, error) + // RemoveUserFromUserGroup allows to remove a specific user from a specific + // user group + RemoveUserFromUserGroup(ctx context.Context, in *MsgRemoveUserFromUserGroup, opts ...grpc.CallOption) (*MsgRemoveUserFromUserGroupResponse, error) + // SetUserPermissions allows to set the permissions for a specific user + SetUserPermissions(ctx context.Context, in *MsgSetUserPermissions, opts ...grpc.CallOption) (*MsgSetUserPermissionsResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) CreateSubspace(ctx context.Context, in *MsgCreateSubspace, opts ...grpc.CallOption) (*MsgCreateSubspaceResponse, error) { + out := new(MsgCreateSubspaceResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/CreateSubspace", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) EditSubspace(ctx context.Context, in *MsgEditSubspace, opts ...grpc.CallOption) (*MsgEditSubspaceResponse, error) { + out := new(MsgEditSubspaceResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/EditSubspace", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) DeleteSubspace(ctx context.Context, in *MsgDeleteSubspace, opts ...grpc.CallOption) (*MsgDeleteSubspaceResponse, error) { + out := new(MsgDeleteSubspaceResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/DeleteSubspace", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) CreateUserGroup(ctx context.Context, in *MsgCreateUserGroup, opts ...grpc.CallOption) (*MsgCreateUserGroupResponse, error) { + out := new(MsgCreateUserGroupResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/CreateUserGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) EditUserGroup(ctx context.Context, in *MsgEditUserGroup, opts ...grpc.CallOption) (*MsgEditUserGroupResponse, error) { + out := new(MsgEditUserGroupResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/EditUserGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) SetUserGroupPermissions(ctx context.Context, in *MsgSetUserGroupPermissions, opts ...grpc.CallOption) (*MsgSetUserGroupPermissionsResponse, error) { + out := new(MsgSetUserGroupPermissionsResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/SetUserGroupPermissions", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) DeleteUserGroup(ctx context.Context, in *MsgDeleteUserGroup, opts ...grpc.CallOption) (*MsgDeleteUserGroupResponse, error) { + out := new(MsgDeleteUserGroupResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/DeleteUserGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) AddUserToUserGroup(ctx context.Context, in *MsgAddUserToUserGroup, opts ...grpc.CallOption) (*MsgAddUserToUserGroupResponse, error) { + out := new(MsgAddUserToUserGroupResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/AddUserToUserGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) RemoveUserFromUserGroup(ctx context.Context, in *MsgRemoveUserFromUserGroup, opts ...grpc.CallOption) (*MsgRemoveUserFromUserGroupResponse, error) { + out := new(MsgRemoveUserFromUserGroupResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/RemoveUserFromUserGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) SetUserPermissions(ctx context.Context, in *MsgSetUserPermissions, opts ...grpc.CallOption) (*MsgSetUserPermissionsResponse, error) { + out := new(MsgSetUserPermissionsResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Msg/SetUserPermissions", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // CreateSubspace allows to create a subspace + CreateSubspace(context.Context, *MsgCreateSubspace) (*MsgCreateSubspaceResponse, error) + // EditSubspace allows to edit a subspace + EditSubspace(context.Context, *MsgEditSubspace) (*MsgEditSubspaceResponse, error) + // DeleteSubspace allows to delete a subspace + DeleteSubspace(context.Context, *MsgDeleteSubspace) (*MsgDeleteSubspaceResponse, error) + // CreateUserGroup allows to create a user group + CreateUserGroup(context.Context, *MsgCreateUserGroup) (*MsgCreateUserGroupResponse, error) + // EditUserGroup allows to edit a user group + EditUserGroup(context.Context, *MsgEditUserGroup) (*MsgEditUserGroupResponse, error) + // SetUserGroupPermissions allows to set the permissions for a specific group + SetUserGroupPermissions(context.Context, *MsgSetUserGroupPermissions) (*MsgSetUserGroupPermissionsResponse, error) + // DeleteUserGroup allows to delete an existing user group + DeleteUserGroup(context.Context, *MsgDeleteUserGroup) (*MsgDeleteUserGroupResponse, error) + // AddUserToUserGroup allows to add a specific user to a specific user group + AddUserToUserGroup(context.Context, *MsgAddUserToUserGroup) (*MsgAddUserToUserGroupResponse, error) + // RemoveUserFromUserGroup allows to remove a specific user from a specific + // user group + RemoveUserFromUserGroup(context.Context, *MsgRemoveUserFromUserGroup) (*MsgRemoveUserFromUserGroupResponse, error) + // SetUserPermissions allows to set the permissions for a specific user + SetUserPermissions(context.Context, *MsgSetUserPermissions) (*MsgSetUserPermissionsResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) CreateSubspace(ctx context.Context, req *MsgCreateSubspace) (*MsgCreateSubspaceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateSubspace not implemented") +} +func (*UnimplementedMsgServer) EditSubspace(ctx context.Context, req *MsgEditSubspace) (*MsgEditSubspaceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EditSubspace not implemented") +} +func (*UnimplementedMsgServer) DeleteSubspace(ctx context.Context, req *MsgDeleteSubspace) (*MsgDeleteSubspaceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteSubspace not implemented") +} +func (*UnimplementedMsgServer) CreateUserGroup(ctx context.Context, req *MsgCreateUserGroup) (*MsgCreateUserGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateUserGroup not implemented") +} +func (*UnimplementedMsgServer) EditUserGroup(ctx context.Context, req *MsgEditUserGroup) (*MsgEditUserGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EditUserGroup not implemented") +} +func (*UnimplementedMsgServer) SetUserGroupPermissions(ctx context.Context, req *MsgSetUserGroupPermissions) (*MsgSetUserGroupPermissionsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetUserGroupPermissions not implemented") +} +func (*UnimplementedMsgServer) DeleteUserGroup(ctx context.Context, req *MsgDeleteUserGroup) (*MsgDeleteUserGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteUserGroup not implemented") +} +func (*UnimplementedMsgServer) AddUserToUserGroup(ctx context.Context, req *MsgAddUserToUserGroup) (*MsgAddUserToUserGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddUserToUserGroup not implemented") +} +func (*UnimplementedMsgServer) RemoveUserFromUserGroup(ctx context.Context, req *MsgRemoveUserFromUserGroup) (*MsgRemoveUserFromUserGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveUserFromUserGroup not implemented") +} +func (*UnimplementedMsgServer) SetUserPermissions(ctx context.Context, req *MsgSetUserPermissions) (*MsgSetUserPermissionsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetUserPermissions not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_CreateSubspace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateSubspace) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateSubspace(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/CreateSubspace", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateSubspace(ctx, req.(*MsgCreateSubspace)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_EditSubspace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgEditSubspace) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).EditSubspace(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/EditSubspace", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).EditSubspace(ctx, req.(*MsgEditSubspace)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_DeleteSubspace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgDeleteSubspace) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).DeleteSubspace(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/DeleteSubspace", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).DeleteSubspace(ctx, req.(*MsgDeleteSubspace)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_CreateUserGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateUserGroup) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateUserGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/CreateUserGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateUserGroup(ctx, req.(*MsgCreateUserGroup)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_EditUserGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgEditUserGroup) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).EditUserGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/EditUserGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).EditUserGroup(ctx, req.(*MsgEditUserGroup)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_SetUserGroupPermissions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSetUserGroupPermissions) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).SetUserGroupPermissions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/SetUserGroupPermissions", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).SetUserGroupPermissions(ctx, req.(*MsgSetUserGroupPermissions)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_DeleteUserGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgDeleteUserGroup) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).DeleteUserGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/DeleteUserGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).DeleteUserGroup(ctx, req.(*MsgDeleteUserGroup)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_AddUserToUserGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgAddUserToUserGroup) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).AddUserToUserGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/AddUserToUserGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).AddUserToUserGroup(ctx, req.(*MsgAddUserToUserGroup)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_RemoveUserFromUserGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRemoveUserFromUserGroup) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RemoveUserFromUserGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/RemoveUserFromUserGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RemoveUserFromUserGroup(ctx, req.(*MsgRemoveUserFromUserGroup)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_SetUserPermissions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSetUserPermissions) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).SetUserPermissions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Msg/SetUserPermissions", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).SetUserPermissions(ctx, req.(*MsgSetUserPermissions)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "desmos.subspaces.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateSubspace", + Handler: _Msg_CreateSubspace_Handler, + }, + { + MethodName: "EditSubspace", + Handler: _Msg_EditSubspace_Handler, + }, + { + MethodName: "DeleteSubspace", + Handler: _Msg_DeleteSubspace_Handler, + }, + { + MethodName: "CreateUserGroup", + Handler: _Msg_CreateUserGroup_Handler, + }, + { + MethodName: "EditUserGroup", + Handler: _Msg_EditUserGroup_Handler, + }, + { + MethodName: "SetUserGroupPermissions", + Handler: _Msg_SetUserGroupPermissions_Handler, + }, + { + MethodName: "DeleteUserGroup", + Handler: _Msg_DeleteUserGroup_Handler, + }, + { + MethodName: "AddUserToUserGroup", + Handler: _Msg_AddUserToUserGroup_Handler, + }, + { + MethodName: "RemoveUserFromUserGroup", + Handler: _Msg_RemoveUserFromUserGroup_Handler, + }, + { + MethodName: "SetUserPermissions", + Handler: _Msg_SetUserPermissions_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "desmos/subspaces/v1/msgs.proto", +} + +func (m *MsgCreateSubspace) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateSubspace) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateSubspace) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0x2a + } + if len(m.Owner) > 0 { + i -= len(m.Owner) + copy(dAtA[i:], m.Owner) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Owner))) + i-- + dAtA[i] = 0x22 + } + if len(m.Treasury) > 0 { + i -= len(m.Treasury) + copy(dAtA[i:], m.Treasury) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Treasury))) + i-- + dAtA[i] = 0x1a + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateSubspaceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateSubspaceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateSubspaceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgEditSubspace) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgEditSubspace) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgEditSubspace) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x32 + } + if len(m.Owner) > 0 { + i -= len(m.Owner) + copy(dAtA[i:], m.Owner) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Owner))) + i-- + dAtA[i] = 0x2a + } + if len(m.Treasury) > 0 { + i -= len(m.Treasury) + copy(dAtA[i:], m.Treasury) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Treasury))) + i-- + dAtA[i] = 0x22 + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x1a + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgEditSubspaceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgEditSubspaceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgEditSubspaceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgDeleteSubspace) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgDeleteSubspace) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDeleteSubspace) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgDeleteSubspaceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgDeleteSubspaceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDeleteSubspaceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgCreateUserGroup) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateUserGroup) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateUserGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0x2a + } + if m.DefaultPermissions != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.DefaultPermissions)) + i-- + dAtA[i] = 0x20 + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x1a + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateUserGroupResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateUserGroupResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateUserGroupResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.GroupID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.GroupID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgEditUserGroup) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgEditUserGroup) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgEditUserGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x2a + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x22 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x1a + } + if m.GroupID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.GroupID)) + i-- + dAtA[i] = 0x10 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgEditUserGroupResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgEditUserGroupResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgEditUserGroupResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgSetUserGroupPermissions) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgSetUserGroupPermissions) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetUserGroupPermissions) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x22 + } + if m.Permissions != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.Permissions)) + i-- + dAtA[i] = 0x18 + } + if m.GroupID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.GroupID)) + i-- + dAtA[i] = 0x10 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgSetUserGroupPermissionsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgSetUserGroupPermissionsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetUserGroupPermissionsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgDeleteUserGroup) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgDeleteUserGroup) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDeleteUserGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x1a + } + if m.GroupID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.GroupID)) + i-- + dAtA[i] = 0x10 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgDeleteUserGroupResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgDeleteUserGroupResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDeleteUserGroupResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgAddUserToUserGroup) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgAddUserToUserGroup) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAddUserToUserGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x22 + } + if len(m.User) > 0 { + i -= len(m.User) + copy(dAtA[i:], m.User) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.User))) + i-- + dAtA[i] = 0x1a + } + if m.GroupID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.GroupID)) + i-- + dAtA[i] = 0x10 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgAddUserToUserGroupResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgAddUserToUserGroupResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAddUserToUserGroupResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgRemoveUserFromUserGroup) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgRemoveUserFromUserGroup) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRemoveUserFromUserGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x22 + } + if len(m.User) > 0 { + i -= len(m.User) + copy(dAtA[i:], m.User) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.User))) + i-- + dAtA[i] = 0x1a + } + if m.GroupID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.GroupID)) + i-- + dAtA[i] = 0x10 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgRemoveUserFromUserGroupResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgRemoveUserFromUserGroupResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRemoveUserFromUserGroupResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgSetUserPermissions) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgSetUserPermissions) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetUserPermissions) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x22 + } + if m.Permissions != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.Permissions)) + i-- + dAtA[i] = 0x18 + } + if len(m.User) > 0 { + i -= len(m.User) + copy(dAtA[i:], m.User) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.User))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgSetUserPermissionsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgSetUserPermissionsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetUserPermissionsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintMsgs(dAtA []byte, offset int, v uint64) int { + offset -= sovMsgs(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgCreateSubspace) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Treasury) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Owner) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgCreateSubspaceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + return n +} + +func (m *MsgEditSubspace) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Treasury) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Owner) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgEditSubspaceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgDeleteSubspace) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgDeleteSubspaceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgCreateUserGroup) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + if m.DefaultPermissions != 0 { + n += 1 + sovMsgs(uint64(m.DefaultPermissions)) + } + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgCreateUserGroupResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupID != 0 { + n += 1 + sovMsgs(uint64(m.GroupID)) + } + return n +} + +func (m *MsgEditUserGroup) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + if m.GroupID != 0 { + n += 1 + sovMsgs(uint64(m.GroupID)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgEditUserGroupResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgSetUserGroupPermissions) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + if m.GroupID != 0 { + n += 1 + sovMsgs(uint64(m.GroupID)) + } + if m.Permissions != 0 { + n += 1 + sovMsgs(uint64(m.Permissions)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgSetUserGroupPermissionsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgDeleteUserGroup) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + if m.GroupID != 0 { + n += 1 + sovMsgs(uint64(m.GroupID)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgDeleteUserGroupResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgAddUserToUserGroup) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + if m.GroupID != 0 { + n += 1 + sovMsgs(uint64(m.GroupID)) + } + l = len(m.User) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgAddUserToUserGroupResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRemoveUserFromUserGroup) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + if m.GroupID != 0 { + n += 1 + sovMsgs(uint64(m.GroupID)) + } + l = len(m.User) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgRemoveUserFromUserGroupResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgSetUserPermissions) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + l = len(m.User) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + if m.Permissions != 0 { + n += 1 + sovMsgs(uint64(m.Permissions)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgSetUserPermissionsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovMsgs(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozMsgs(x uint64) (n int) { + return sovMsgs(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgCreateSubspace) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateSubspace: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateSubspace: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Treasury", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Treasury = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Owner = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateSubspaceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateSubspaceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateSubspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgEditSubspace) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgEditSubspace: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgEditSubspace: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Treasury", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Treasury = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Owner = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgEditSubspaceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgEditSubspaceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgEditSubspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgDeleteSubspace) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgDeleteSubspace: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDeleteSubspace: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgDeleteSubspaceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgDeleteSubspaceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDeleteSubspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateUserGroup) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateUserGroup: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateUserGroup: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DefaultPermissions", wireType) + } + m.DefaultPermissions = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DefaultPermissions |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateUserGroupResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateUserGroupResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateUserGroupResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupID", wireType) + } + m.GroupID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgEditUserGroup) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgEditUserGroup: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgEditUserGroup: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupID", wireType) + } + m.GroupID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgEditUserGroupResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgEditUserGroupResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgEditUserGroupResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetUserGroupPermissions) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgSetUserGroupPermissions: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetUserGroupPermissions: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupID", wireType) + } + m.GroupID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) + } + m.Permissions = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Permissions |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetUserGroupPermissionsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgSetUserGroupPermissionsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetUserGroupPermissionsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgDeleteUserGroup) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgDeleteUserGroup: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDeleteUserGroup: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupID", wireType) + } + m.GroupID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgDeleteUserGroupResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgDeleteUserGroupResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDeleteUserGroupResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgAddUserToUserGroup) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgAddUserToUserGroup: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAddUserToUserGroup: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupID", wireType) + } + m.GroupID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.User = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgAddUserToUserGroupResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgAddUserToUserGroupResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAddUserToUserGroupResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRemoveUserFromUserGroup) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgRemoveUserFromUserGroup: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRemoveUserFromUserGroup: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupID", wireType) + } + m.GroupID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupID |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.User = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRemoveUserFromUserGroupResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgRemoveUserFromUserGroupResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRemoveUserFromUserGroupResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetUserPermissions) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgSetUserPermissions: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetUserPermissions: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.User = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) + } + m.Permissions = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Permissions |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetUserPermissionsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgSetUserPermissionsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetUserPermissionsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipMsgs(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMsgs + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMsgs + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMsgs + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthMsgs + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupMsgs + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthMsgs + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthMsgs = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowMsgs = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupMsgs = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/subspaces/types/msgs_test.go b/x/subspaces/types/msgs_test.go new file mode 100644 index 0000000000..a0b40cb0ad --- /dev/null +++ b/x/subspaces/types/msgs_test.go @@ -0,0 +1,840 @@ +package types_test + +import ( + "testing" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +var msgCreateSubspace = types.NewMsgCreateSubspace( + "Test subspace", + "This is a test subspace", + "cosmos1vkuuth0rak58x36m7wuzj7ztttxh26fhqcfxm0", + "cosmos1lv3e0l66rr68k5l74mnrv4j9kyny6cz27pvnez", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", +) + +func TestMsgCreateSubspace_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgCreateSubspace.Route()) +} + +func TestMsgCreateSubspace_Type(t *testing.T) { + require.Equal(t, types.ActionCreateSubspace, msgCreateSubspace.Type()) +} + +func TestMsgCreateSubspace_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgCreateSubspace + shouldErr bool + }{ + { + name: "invalid name returns error", + msg: types.NewMsgCreateSubspace( + "", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + ), + shouldErr: true, + }, + { + name: "invalid treasury returns error", + msg: types.NewMsgCreateSubspace( + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + ), + shouldErr: true, + }, + { + name: "invalid owner returns error", + msg: types.NewMsgCreateSubspace( + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4ye", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + ), + shouldErr: true, + }, + { + name: "invalid creator returns error", + msg: types.NewMsgCreateSubspace( + "Test subspace", + "This is a test subspace", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgCreateSubspace, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgCreateSubspace_GetSignBytes(t *testing.T) { + expected := `{"creator":"cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69","description":"This is a test subspace","name":"Test subspace","owner":"cosmos1lv3e0l66rr68k5l74mnrv4j9kyny6cz27pvnez","treasury":"cosmos1vkuuth0rak58x36m7wuzj7ztttxh26fhqcfxm0"}` + require.Equal(t, expected, string(msgCreateSubspace.GetSignBytes())) +} + +func TestMsgCreateSubspace_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgCreateSubspace.Creator) + require.Equal(t, []sdk.AccAddress{addr}, msgCreateSubspace.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgEditSubspace = types.NewMsgEditSubspace( + 1, + "This is a new name", + "This is a new description", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", +) + +func TestMsgEditSubspace_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgEditSubspace.Route()) +} + +func TestMsgEditSubspace_Type(t *testing.T) { + require.Equal(t, types.ActionEditSubspace, msgEditSubspace.Type()) +} + +func TestMsgEditSubspace_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgEditSubspace + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgEditSubspace( + 0, + "This is a new name", + "This is a new description", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid signer returns error", + msg: types.NewMsgEditSubspace( + 1, + "This is a new name", + "This is a new description", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1m0czrla04f7rp3z", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgEditSubspace, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgEditSubspace_GetSignBytes(t *testing.T) { + expected := `{"description":"This is a new description","name":"This is a new name","owner":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","signer":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","subspace_id":"1","treasury":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5"}` + require.Equal(t, expected, string(msgEditSubspace.GetSignBytes())) +} + +func TestMsgEditSubspace_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgEditSubspace.Signer) + require.Equal(t, []sdk.AccAddress{addr}, msgEditSubspace.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgDeleteSubspace = types.NewMsgDeleteSubspace( + 1, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", +) + +func TestMsgDeleteSubspace_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgDeleteSubspace.Route()) +} + +func TestMsgDeleteSubspace_Type(t *testing.T) { + require.Equal(t, types.ActionEditSubspace, msgDeleteSubspace.Type()) +} + +func TestMsgDeleteSubspace_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgDeleteSubspace + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgDeleteSubspace(0, "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5"), + shouldErr: true, + }, + { + name: "invalid signer returns error", + msg: types.NewMsgDeleteSubspace(1, "cosmos1m0czrla04f7rp3z"), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgDeleteSubspace, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgDeleteSubspace_GetSignBytes(t *testing.T) { + expected := `{"signer":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","subspace_id":"1"}` + require.Equal(t, expected, string(msgDeleteSubspace.GetSignBytes())) +} + +func TestMsgDeleteSubspace_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgDeleteSubspace.Signer) + require.Equal(t, []sdk.AccAddress{addr}, msgDeleteSubspace.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgCreateUserGroup = types.NewMsgCreateUserGroup( + 1, + "Group", + "Description", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", +) + +func TestMsgCreateUserGroup_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgCreateUserGroup.Route()) +} + +func TestMsgCreateUserGroup_Type(t *testing.T) { + require.Equal(t, types.ActionCreateUserGroup, msgCreateUserGroup.Type()) +} + +func TestMsgCreateUserGroup_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgCreateUserGroup + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgCreateUserGroup( + 0, + "group", + "description", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid group name returns error", + msg: types.NewMsgCreateUserGroup( + 1, + "", + "description", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid creator returns error", + msg: types.NewMsgCreateUserGroup( + 1, + "group", + "description", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kl", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgCreateUserGroup, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgCreateUserGroup_GetSignBytes(t *testing.T) { + expected := `{"creator":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","default_permissions":1,"description":"Description","name":"Group","subspace_id":"1"}` + require.Equal(t, expected, string(msgCreateUserGroup.GetSignBytes())) +} + +func TestMsgCreateUserGroup_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgCreateUserGroup.Creator) + require.Equal(t, []sdk.AccAddress{addr}, msgCreateUserGroup.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgEditUserGroup = types.NewMsgEditUserGroup( + 1, + 1, + "Group", + "Description", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", +) + +func TestMsgEditUserGroup_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgEditUserGroup.Route()) +} + +func TestMsgEditUserGroup_Type(t *testing.T) { + require.Equal(t, types.ActionEditUserGroup, msgEditUserGroup.Type()) +} + +func TestMsgEditUserGroup_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgEditUserGroup + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgEditUserGroup( + 0, + 1, + "group", + "description", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid group name returns error", + msg: types.NewMsgEditUserGroup( + 1, + 0, + "group", + "description", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid creator returns error", + msg: types.NewMsgEditUserGroup( + 1, + 1, + "group", + "description", + "cosmos1m0czrla04f7rp3zg7dsgc4kl", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgEditUserGroup, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgEditUserGroup_GetSignBytes(t *testing.T) { + expected := `{"description":"Description","group_id":1,"name":"Group","signer":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","subspace_id":"1"}` + require.Equal(t, expected, string(msgEditUserGroup.GetSignBytes())) +} + +func TestMsgEditUserGroup_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgEditUserGroup.Signer) + require.Equal(t, []sdk.AccAddress{addr}, msgEditUserGroup.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgSetUserGroupPermissions = types.NewMsgSetUserGroupPermissions( + 1, + 1, + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", +) + +func TestMsgSetUserGroupPermissions_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgSetUserGroupPermissions.Route()) +} + +func TestMsgSetUserGroupPermissions_Type(t *testing.T) { + require.Equal(t, types.ActionSetUserGroupPermissions, msgSetUserGroupPermissions.Type()) +} + +func TestMsgSetUserGroupPermissions_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgSetUserGroupPermissions + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgSetUserGroupPermissions( + 0, + 1, + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid group id returns error", + msg: types.NewMsgSetUserGroupPermissions( + 1, + 0, + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid creator returns error", + msg: types.NewMsgSetUserGroupPermissions( + 1, + 1, + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kl", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgSetUserGroupPermissions, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgSetUserGroupPermissions_GetSignBytes(t *testing.T) { + expected := `{"group_id":1,"permissions":1,"signer":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","subspace_id":"1"}` + require.Equal(t, expected, string(msgSetUserGroupPermissions.GetSignBytes())) +} + +func TestMsgSetUserGroupPermissions_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgSetUserGroupPermissions.Signer) + require.Equal(t, []sdk.AccAddress{addr}, msgSetUserGroupPermissions.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgDeleteUserGroup = types.NewMsgDeleteUserGroup( + 1, + 1, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", +) + +func TestMsgDeleteUserGroup_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgDeleteUserGroup.Route()) +} + +func TestMsgDeleteUserGroup_Type(t *testing.T) { + require.Equal(t, types.ActionDeleteUserGroup, msgDeleteUserGroup.Type()) +} + +func TestMsgDeleteUserGroup_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgDeleteUserGroup + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgDeleteUserGroup( + 0, + 1, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid group id returns error", + msg: types.NewMsgDeleteUserGroup( + 1, + 0, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid signer returns error", + msg: types.NewMsgDeleteUserGroup( + 1, + 1, + "cosmos1m0czrla04f7rp3zg7dsgc4kl", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgDeleteUserGroup, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgDeleteUserGroup_GetSignBytes(t *testing.T) { + expected := `{"group_id":1,"signer":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","subspace_id":"1"}` + require.Equal(t, expected, string(msgDeleteUserGroup.GetSignBytes())) +} + +func TestMsgDeleteUserGroup_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgDeleteUserGroup.Signer) + require.Equal(t, []sdk.AccAddress{addr}, msgDeleteUserGroup.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgAddUserToGroup = types.NewMsgAddUserToUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", +) + +func TestMsgAddUserToUserGroup_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgAddUserToGroup.Route()) +} + +func TestMsgAddUserToUserGroup_Type(t *testing.T) { + require.Equal(t, types.ActionAddUserToUserGroup, msgAddUserToGroup.Type()) +} + +func TestMsgAddUserToUserGroup_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgAddUserToUserGroup + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgAddUserToUserGroup( + 0, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid group id returns error", + msg: types.NewMsgAddUserToUserGroup( + 1, + 0, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid user returns error", + msg: types.NewMsgAddUserToUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znn", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid signer returns error", + msg: types.NewMsgAddUserToUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7d", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgAddUserToGroup, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgAddUserToUserGroup_GetSignBytes(t *testing.T) { + expected := `{"group_id":1,"signer":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","subspace_id":"1","user":"cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"}` + require.Equal(t, expected, string(msgAddUserToGroup.GetSignBytes())) +} + +func TestMsgAddUserToUserGroup_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgAddUserToGroup.Signer) + require.Equal(t, []sdk.AccAddress{addr}, msgAddUserToGroup.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgRemoveUserFromUserGroup = types.NewMsgRemoveUserFromUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", +) + +func TestMsgRemoveUserFromUserGroup_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgRemoveUserFromUserGroup.Route()) +} + +func TestMsgRemoveUserFromUserGroup_Type(t *testing.T) { + require.Equal(t, types.ActionRemoveUserFromUserGroup, msgRemoveUserFromUserGroup.Type()) +} + +func TestMsgRemoveUserFromUserGroup_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgRemoveUserFromUserGroup + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgRemoveUserFromUserGroup( + 0, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid group id returns error", + msg: types.NewMsgRemoveUserFromUserGroup( + 1, + 0, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid user returns error", + msg: types.NewMsgRemoveUserFromUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znn", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid signer returns error", + msg: types.NewMsgRemoveUserFromUserGroup( + 1, + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + "cosmos1m0czrla04f7rp3zg7d", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgRemoveUserFromUserGroup, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgRemoveUserFromUserGroup_GetSignBytes(t *testing.T) { + expected := `{"group_id":1,"signer":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","subspace_id":"1","user":"cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"}` + require.Equal(t, expected, string(msgRemoveUserFromUserGroup.GetSignBytes())) +} + +func TestMsgRemoveUserFromUserGroup_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgRemoveUserFromUserGroup.Signer) + require.Equal(t, []sdk.AccAddress{addr}, msgRemoveUserFromUserGroup.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- +var msgSetUserPermissions = types.NewMsgSetUserPermissions( + 1, + "cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", +) + +func TestMsgSetUserPermissions_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgSetUserPermissions.Route()) +} + +func TestMsgSetUserPermissions_Type(t *testing.T) { + require.Equal(t, types.ActionSetUserPermissions, msgSetUserPermissions.Type()) +} + +func TestMsgSetUserPermissions_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgSetUserPermissions + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgSetUserPermissions( + 0, + "group", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid target returns error", + msg: types.NewMsgSetUserPermissions( + 1, + "", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + ), + shouldErr: true, + }, + { + name: "invalid signer returns error", + msg: types.NewMsgSetUserPermissions( + 1, + "group", + types.PermissionWrite, + "cosmos1m0czrla04f7rp3zg7d", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgSetUserPermissions, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgSetUserPermissions_GetSignBytes(t *testing.T) { + expected := `{"permissions":1,"signer":"cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5","subspace_id":"1","user":"cosmos1x5pjlvufs4znnhhkwe8v4tw3kz30f3lxgwza53"}` + require.Equal(t, expected, string(msgSetUserPermissions.GetSignBytes())) +} + +func TestMsgSetUserPermissions_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgSetUserPermissions.Signer) + require.Equal(t, []sdk.AccAddress{addr}, msgSetUserPermissions.GetSigners()) +} diff --git a/x/subspaces/types/permissions.go b/x/subspaces/types/permissions.go new file mode 100644 index 0000000000..11ce4020af --- /dev/null +++ b/x/subspaces/types/permissions.go @@ -0,0 +1,96 @@ +package types + +import ( + "encoding/binary" + "fmt" + "strings" +) + +// Permission represents a permission that can be set to a user or user group +type Permission = uint32 + +const ( + // PermissionNothing represents the permission to do nothing + PermissionNothing = Permission(0b000000) + + // PermissionWrite identifies users that can create content inside the subspace + PermissionWrite = Permission(0b000001) + + // PermissionModerateContent allows users to moderate contents of other users (e.g. deleting it) + PermissionModerateContent = Permission(0b000010) + + // PermissionChangeInfo allows to change the information of the subspace + PermissionChangeInfo = Permission(0b000100) + + // PermissionManageGroups allows users to manage user groups and members + PermissionManageGroups = Permission(0b001000) + + // PermissionSetPermissions allows users to set other users' permissions (except PermissionSetPermissions). + // This includes managing user groups and the associated permissions + PermissionSetPermissions = Permission(0b010000) + + // PermissionDeleteSubspace allows users to delete the subspace. + PermissionDeleteSubspace = Permission(0b100000) + + // PermissionEverything allows to do everything. + // This should usually be reserved only to the owner (which has it by default) + PermissionEverything = Permission(0b111111) +) + +var ( + permissionsMap = map[Permission]string{ + PermissionNothing: "Nothing", + PermissionWrite: "Write", + PermissionModerateContent: "ModerateContent", + PermissionChangeInfo: "ChangeInfo", + PermissionManageGroups: "ManageGroups", + PermissionSetPermissions: "SetUserPermissions", + PermissionEverything: "Everything", + } +) + +// ParsePermission parses the given permission string as a single Permissions instance +func ParsePermission(permission string) (Permission, error) { + // Check inside the map if we have anything here + for permValue, permString := range permissionsMap { + if strings.EqualFold(permission, permString) { + return permValue, nil + } + } + + return 0, fmt.Errorf("invalid permission value: %s", permission) +} + +// SerializePermission serializes the given permission to a string value +func SerializePermission(permission Permission) string { + return permissionsMap[permission] +} + +// MarshalPermission marshals the given permission to a byte array +func MarshalPermission(permission Permission) (permissionBytes []byte) { + permissionBytes = make([]byte, 4) + binary.BigEndian.PutUint32(permissionBytes, permission) + return +} + +// UnmarshalPermission reads the given byte array as a Permission object +func UnmarshalPermission(bz []byte) (permission Permission) { + if len(bz) < 4 { + return PermissionNothing + } + return binary.BigEndian.Uint32(bz) +} + +// CheckPermission checks whether the given permissions contain the specified permission +func CheckPermission(permissions Permission, permission Permission) bool { + return (permissions & permission) == permission +} + +// CombinePermissions combines all the given permissions into a single Permission object using the OR operator +func CombinePermissions(permissions ...Permission) Permission { + result := PermissionNothing + for _, permission := range permissions { + result |= permission + } + return result +} diff --git a/x/subspaces/types/permissions_test.go b/x/subspaces/types/permissions_test.go new file mode 100644 index 0000000000..77f29639d2 --- /dev/null +++ b/x/subspaces/types/permissions_test.go @@ -0,0 +1,157 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/desmos-labs/desmos/v2/x/subspaces/types" +) + +func TestMarshalPermission(t *testing.T) { + testCases := []struct { + name string + permission types.Permission + expected []byte + }{ + { + name: "zero permission", + permission: types.PermissionNothing, + expected: []byte{0, 0, 0, 0}, + }, + { + name: "non-zero permission", + permission: types.PermissionManageGroups, + expected: []byte{0, 0, 0, 8}, + }, + { + name: "high permission", + permission: types.PermissionSetPermissions, + expected: []byte{0, 0, 0, 16}, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + bz := types.MarshalPermission(tc.permission) + require.Equal(t, tc.expected, bz) + }) + } +} + +func TestUnmarshalPermission(t *testing.T) { + testCases := []struct { + name string + bz []byte + expected types.Permission + }{ + { + name: "empty byte array", + bz: []byte{}, + expected: types.PermissionNothing, + }, + { + name: "nil bytes array", + bz: nil, + expected: types.PermissionNothing, + }, + { + name: "zero permission", + bz: []byte{0, 0, 0, 0}, + expected: types.PermissionNothing, + }, + { + name: "non-zero permission", + bz: []byte{0, 0, 0, 4}, + expected: types.PermissionChangeInfo, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + permission := types.UnmarshalPermission(tc.bz) + require.Equal(t, tc.expected, permission) + }) + } +} + +func TestCheckPermission(t *testing.T) { + testCases := []struct { + name string + permissions types.Permission + permission types.Permission + expResult bool + }{ + { + name: "same permission returns true", + permissions: types.PermissionWrite, + permission: types.PermissionWrite, + expResult: true, + }, + { + name: "different permission returns false", + permissions: types.PermissionWrite, + permission: types.PermissionSetPermissions, + expResult: false, + }, + { + name: "combined permission returns true when contains", + permissions: types.PermissionWrite | types.PermissionModerateContent | types.PermissionManageGroups, + permission: types.PermissionModerateContent, + expResult: true, + }, + { + name: "combined permission returns false when does not contain", + permissions: types.PermissionWrite | types.PermissionModerateContent | types.PermissionManageGroups, + permission: types.PermissionSetPermissions, + expResult: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + result := types.CheckPermission(tc.permissions, tc.permission) + require.Equal(t, tc.expResult, result) + }) + } +} + +func TestCombinePermissions(t *testing.T) { + testCases := []struct { + name string + permissions []types.Permission + expResult types.Permission + }{ + { + name: "combining the same permission returns the permission itself", + permissions: []types.Permission{types.PermissionWrite, types.PermissionWrite}, + expResult: types.PermissionWrite, + }, + { + name: "combining anything with PermissionNothing returns the permission itself", + permissions: []types.Permission{types.PermissionNothing, types.PermissionWrite}, + expResult: types.PermissionWrite, + }, + { + name: "combining anything with PermissionEverything returns PermissionEverything", + permissions: []types.Permission{types.PermissionWrite, types.PermissionEverything}, + expResult: types.PermissionEverything, + }, + { + name: "combining different permissions returns the correct result", + permissions: []types.Permission{types.PermissionWrite, types.PermissionManageGroups, types.PermissionSetPermissions}, + expResult: types.PermissionWrite | types.PermissionManageGroups | types.PermissionSetPermissions, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + result := types.CombinePermissions(tc.permissions...) + require.Equal(t, tc.expResult, result) + }) + } +} diff --git a/x/subspaces/types/query.go b/x/subspaces/types/query.go new file mode 100644 index 0000000000..c81d0809b2 --- /dev/null +++ b/x/subspaces/types/query.go @@ -0,0 +1,54 @@ +package types + +// DONTCOVER + +import ( + "github.com/cosmos/cosmos-sdk/types/query" +) + +// NewQuerySubspaceRequest returns a new QuerySubspaceRequest instance +func NewQuerySubspaceRequest(subspaceID uint64) *QuerySubspaceRequest { + return &QuerySubspaceRequest{SubspaceId: subspaceID} +} + +// NewQuerySubspacesRequest returns a new QuerySubspacesRequest instance +func NewQuerySubspacesRequest(pagination *query.PageRequest) *QuerySubspacesRequest { + return &QuerySubspacesRequest{ + Pagination: pagination, + } +} + +// NewQueryUserGroupsRequest returns a new QueryUserGroupsRequest instance +func NewQueryUserGroupsRequest(subspaceID uint64, pagination *query.PageRequest) *QueryUserGroupsRequest { + return &QueryUserGroupsRequest{ + SubspaceId: subspaceID, + Pagination: pagination, + } +} + +// NewQueryUserGroupRequest returns a new QueryUserGroupRequest instance +func NewQueryUserGroupRequest(subspaceID uint64, groupID uint32) *QueryUserGroupRequest { + return &QueryUserGroupRequest{ + SubspaceId: subspaceID, + GroupId: groupID, + } +} + +// NewQueryUserGroupMembersRequest returns a new QueryUserGroupMembersRequest instance +func NewQueryUserGroupMembersRequest( + subspaceID uint64, groupID uint32, pagination *query.PageRequest, +) *QueryUserGroupMembersRequest { + return &QueryUserGroupMembersRequest{ + SubspaceId: subspaceID, + GroupId: groupID, + Pagination: pagination, + } +} + +// NewQueryUserPermissionsRequest returns a new QueryPermissionsRequest instance +func NewQueryUserPermissionsRequest(subspaceID uint64, user string) *QueryUserPermissionsRequest { + return &QueryUserPermissionsRequest{ + SubspaceId: subspaceID, + User: user, + } +} diff --git a/x/subspaces/types/query.pb.go b/x/subspaces/types/query.pb.go new file mode 100644 index 0000000000..636bb79103 --- /dev/null +++ b/x/subspaces/types/query.pb.go @@ -0,0 +1,2940 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/subspaces/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QuerySubspacesRequest is the request type for the Query/Subspaces RPC method +type QuerySubspacesRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QuerySubspacesRequest) Reset() { *m = QuerySubspacesRequest{} } +func (m *QuerySubspacesRequest) String() string { return proto.CompactTextString(m) } +func (*QuerySubspacesRequest) ProtoMessage() {} +func (*QuerySubspacesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{0} +} +func (m *QuerySubspacesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySubspacesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySubspacesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySubspacesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySubspacesRequest.Merge(m, src) +} +func (m *QuerySubspacesRequest) XXX_Size() int { + return m.Size() +} +func (m *QuerySubspacesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySubspacesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySubspacesRequest proto.InternalMessageInfo + +func (m *QuerySubspacesRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QuerySubspacesResponse is the response type for the Query/Subspaces RPC +// method +type QuerySubspacesResponse struct { + Subspaces []Subspace `protobuf:"bytes,1,rep,name=subspaces,proto3" json:"subspaces"` + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QuerySubspacesResponse) Reset() { *m = QuerySubspacesResponse{} } +func (m *QuerySubspacesResponse) String() string { return proto.CompactTextString(m) } +func (*QuerySubspacesResponse) ProtoMessage() {} +func (*QuerySubspacesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{1} +} +func (m *QuerySubspacesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySubspacesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySubspacesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySubspacesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySubspacesResponse.Merge(m, src) +} +func (m *QuerySubspacesResponse) XXX_Size() int { + return m.Size() +} +func (m *QuerySubspacesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySubspacesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySubspacesResponse proto.InternalMessageInfo + +func (m *QuerySubspacesResponse) GetSubspaces() []Subspace { + if m != nil { + return m.Subspaces + } + return nil +} + +func (m *QuerySubspacesResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QuerySubspace is the request type for the Query/Subspace RPC method +type QuerySubspaceRequest struct { + SubspaceId uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` +} + +func (m *QuerySubspaceRequest) Reset() { *m = QuerySubspaceRequest{} } +func (m *QuerySubspaceRequest) String() string { return proto.CompactTextString(m) } +func (*QuerySubspaceRequest) ProtoMessage() {} +func (*QuerySubspaceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{2} +} +func (m *QuerySubspaceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySubspaceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySubspaceRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySubspaceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySubspaceRequest.Merge(m, src) +} +func (m *QuerySubspaceRequest) XXX_Size() int { + return m.Size() +} +func (m *QuerySubspaceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySubspaceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySubspaceRequest proto.InternalMessageInfo + +// QuerySubspaceResponse is the response type for the Query/Subspace method +type QuerySubspaceResponse struct { + Subspace Subspace `protobuf:"bytes,1,opt,name=subspace,proto3" json:"subspace"` +} + +func (m *QuerySubspaceResponse) Reset() { *m = QuerySubspaceResponse{} } +func (m *QuerySubspaceResponse) String() string { return proto.CompactTextString(m) } +func (*QuerySubspaceResponse) ProtoMessage() {} +func (*QuerySubspaceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{3} +} +func (m *QuerySubspaceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySubspaceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySubspaceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySubspaceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySubspaceResponse.Merge(m, src) +} +func (m *QuerySubspaceResponse) XXX_Size() int { + return m.Size() +} +func (m *QuerySubspaceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySubspaceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySubspaceResponse proto.InternalMessageInfo + +func (m *QuerySubspaceResponse) GetSubspace() Subspace { + if m != nil { + return m.Subspace + } + return Subspace{} +} + +// QueryUserGroupsRequest is the request type for the Query/UserGroups RPC +// method +type QueryUserGroupsRequest struct { + SubspaceId uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryUserGroupsRequest) Reset() { *m = QueryUserGroupsRequest{} } +func (m *QueryUserGroupsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryUserGroupsRequest) ProtoMessage() {} +func (*QueryUserGroupsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{4} +} +func (m *QueryUserGroupsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUserGroupsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUserGroupsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUserGroupsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUserGroupsRequest.Merge(m, src) +} +func (m *QueryUserGroupsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryUserGroupsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUserGroupsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUserGroupsRequest proto.InternalMessageInfo + +func (m *QueryUserGroupsRequest) GetSubspaceId() uint64 { + if m != nil { + return m.SubspaceId + } + return 0 +} + +func (m *QueryUserGroupsRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryUserGroupsResponse is the response type for the Query/UserGroups RPC +// method +type QueryUserGroupsResponse struct { + Groups []UserGroup `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups"` + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryUserGroupsResponse) Reset() { *m = QueryUserGroupsResponse{} } +func (m *QueryUserGroupsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryUserGroupsResponse) ProtoMessage() {} +func (*QueryUserGroupsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{5} +} +func (m *QueryUserGroupsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUserGroupsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUserGroupsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUserGroupsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUserGroupsResponse.Merge(m, src) +} +func (m *QueryUserGroupsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryUserGroupsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUserGroupsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUserGroupsResponse proto.InternalMessageInfo + +func (m *QueryUserGroupsResponse) GetGroups() []UserGroup { + if m != nil { + return m.Groups + } + return nil +} + +func (m *QueryUserGroupsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryUserGroupRequest is the request type for the Query/UserGroup RPC method +type QueryUserGroupRequest struct { + SubspaceId uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + GroupId uint32 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty" yaml:"group_id"` +} + +func (m *QueryUserGroupRequest) Reset() { *m = QueryUserGroupRequest{} } +func (m *QueryUserGroupRequest) String() string { return proto.CompactTextString(m) } +func (*QueryUserGroupRequest) ProtoMessage() {} +func (*QueryUserGroupRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{6} +} +func (m *QueryUserGroupRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUserGroupRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUserGroupRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUserGroupRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUserGroupRequest.Merge(m, src) +} +func (m *QueryUserGroupRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryUserGroupRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUserGroupRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUserGroupRequest proto.InternalMessageInfo + +func (m *QueryUserGroupRequest) GetSubspaceId() uint64 { + if m != nil { + return m.SubspaceId + } + return 0 +} + +func (m *QueryUserGroupRequest) GetGroupId() uint32 { + if m != nil { + return m.GroupId + } + return 0 +} + +// QueryUserGroupResponse is the response type for the Query/UserGroup RPC +// method +type QueryUserGroupResponse struct { + Group UserGroup `protobuf:"bytes,1,opt,name=group,proto3" json:"group"` +} + +func (m *QueryUserGroupResponse) Reset() { *m = QueryUserGroupResponse{} } +func (m *QueryUserGroupResponse) String() string { return proto.CompactTextString(m) } +func (*QueryUserGroupResponse) ProtoMessage() {} +func (*QueryUserGroupResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{7} +} +func (m *QueryUserGroupResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUserGroupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUserGroupResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUserGroupResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUserGroupResponse.Merge(m, src) +} +func (m *QueryUserGroupResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryUserGroupResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUserGroupResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUserGroupResponse proto.InternalMessageInfo + +func (m *QueryUserGroupResponse) GetGroup() UserGroup { + if m != nil { + return m.Group + } + return UserGroup{} +} + +// QueryUserGroupMembersRequest is the request type for the +// Query/UserGroupMembers RPC method +type QueryUserGroupMembersRequest struct { + SubspaceId uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + GroupId uint32 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty" yaml:"group_id"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,3,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryUserGroupMembersRequest) Reset() { *m = QueryUserGroupMembersRequest{} } +func (m *QueryUserGroupMembersRequest) String() string { return proto.CompactTextString(m) } +func (*QueryUserGroupMembersRequest) ProtoMessage() {} +func (*QueryUserGroupMembersRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{8} +} +func (m *QueryUserGroupMembersRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUserGroupMembersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUserGroupMembersRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUserGroupMembersRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUserGroupMembersRequest.Merge(m, src) +} +func (m *QueryUserGroupMembersRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryUserGroupMembersRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUserGroupMembersRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUserGroupMembersRequest proto.InternalMessageInfo + +func (m *QueryUserGroupMembersRequest) GetSubspaceId() uint64 { + if m != nil { + return m.SubspaceId + } + return 0 +} + +func (m *QueryUserGroupMembersRequest) GetGroupId() uint32 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *QueryUserGroupMembersRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryUserGroupMembersResponse is the response type for the +// Query/UserGroupMembers RPC method +type QueryUserGroupMembersResponse struct { + Members []string `protobuf:"bytes,1,rep,name=members,proto3" json:"members,omitempty"` + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryUserGroupMembersResponse) Reset() { *m = QueryUserGroupMembersResponse{} } +func (m *QueryUserGroupMembersResponse) String() string { return proto.CompactTextString(m) } +func (*QueryUserGroupMembersResponse) ProtoMessage() {} +func (*QueryUserGroupMembersResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{9} +} +func (m *QueryUserGroupMembersResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUserGroupMembersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUserGroupMembersResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUserGroupMembersResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUserGroupMembersResponse.Merge(m, src) +} +func (m *QueryUserGroupMembersResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryUserGroupMembersResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUserGroupMembersResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUserGroupMembersResponse proto.InternalMessageInfo + +func (m *QueryUserGroupMembersResponse) GetMembers() []string { + if m != nil { + return m.Members + } + return nil +} + +func (m *QueryUserGroupMembersResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryUserPermissionsRequest is the request type for the Query/UserPermissions +// RPC method +type QueryUserPermissionsRequest struct { + SubspaceId uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + User string `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty" yaml:"user"` +} + +func (m *QueryUserPermissionsRequest) Reset() { *m = QueryUserPermissionsRequest{} } +func (m *QueryUserPermissionsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryUserPermissionsRequest) ProtoMessage() {} +func (*QueryUserPermissionsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{10} +} +func (m *QueryUserPermissionsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUserPermissionsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUserPermissionsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUserPermissionsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUserPermissionsRequest.Merge(m, src) +} +func (m *QueryUserPermissionsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryUserPermissionsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUserPermissionsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUserPermissionsRequest proto.InternalMessageInfo + +// QueryUserPermissionsRequest is the response type for the +// Query/UserPermissions method +type QueryUserPermissionsResponse struct { + Permissions uint32 `protobuf:"varint,1,opt,name=permissions,proto3" json:"permissions,omitempty" yaml:"permissions"` + Details []PermissionDetail `protobuf:"bytes,2,rep,name=details,proto3" json:"details" yaml:"details"` +} + +func (m *QueryUserPermissionsResponse) Reset() { *m = QueryUserPermissionsResponse{} } +func (m *QueryUserPermissionsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryUserPermissionsResponse) ProtoMessage() {} +func (*QueryUserPermissionsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_883a12b013a133fc, []int{11} +} +func (m *QueryUserPermissionsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUserPermissionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUserPermissionsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUserPermissionsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUserPermissionsResponse.Merge(m, src) +} +func (m *QueryUserPermissionsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryUserPermissionsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUserPermissionsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUserPermissionsResponse proto.InternalMessageInfo + +func (m *QueryUserPermissionsResponse) GetPermissions() uint32 { + if m != nil { + return m.Permissions + } + return 0 +} + +func (m *QueryUserPermissionsResponse) GetDetails() []PermissionDetail { + if m != nil { + return m.Details + } + return nil +} + +func init() { + proto.RegisterType((*QuerySubspacesRequest)(nil), "desmos.subspaces.v1.QuerySubspacesRequest") + proto.RegisterType((*QuerySubspacesResponse)(nil), "desmos.subspaces.v1.QuerySubspacesResponse") + proto.RegisterType((*QuerySubspaceRequest)(nil), "desmos.subspaces.v1.QuerySubspaceRequest") + proto.RegisterType((*QuerySubspaceResponse)(nil), "desmos.subspaces.v1.QuerySubspaceResponse") + proto.RegisterType((*QueryUserGroupsRequest)(nil), "desmos.subspaces.v1.QueryUserGroupsRequest") + proto.RegisterType((*QueryUserGroupsResponse)(nil), "desmos.subspaces.v1.QueryUserGroupsResponse") + proto.RegisterType((*QueryUserGroupRequest)(nil), "desmos.subspaces.v1.QueryUserGroupRequest") + proto.RegisterType((*QueryUserGroupResponse)(nil), "desmos.subspaces.v1.QueryUserGroupResponse") + proto.RegisterType((*QueryUserGroupMembersRequest)(nil), "desmos.subspaces.v1.QueryUserGroupMembersRequest") + proto.RegisterType((*QueryUserGroupMembersResponse)(nil), "desmos.subspaces.v1.QueryUserGroupMembersResponse") + proto.RegisterType((*QueryUserPermissionsRequest)(nil), "desmos.subspaces.v1.QueryUserPermissionsRequest") + proto.RegisterType((*QueryUserPermissionsResponse)(nil), "desmos.subspaces.v1.QueryUserPermissionsResponse") +} + +func init() { proto.RegisterFile("desmos/subspaces/v1/query.proto", fileDescriptor_883a12b013a133fc) } + +var fileDescriptor_883a12b013a133fc = []byte{ + // 849 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x4f, 0x13, 0x41, + 0x14, 0xee, 0x94, 0x5f, 0xed, 0x34, 0x88, 0x19, 0x10, 0x9b, 0x0a, 0xbb, 0xcd, 0x1a, 0x11, 0x01, + 0x77, 0x6d, 0xd1, 0x68, 0xd0, 0x88, 0x34, 0x06, 0x24, 0x51, 0x83, 0xab, 0xc6, 0x1f, 0x17, 0xb2, + 0xa5, 0x93, 0xb5, 0x49, 0xdb, 0x5d, 0x3a, 0xdb, 0x46, 0x42, 0x48, 0x0c, 0x89, 0x89, 0x07, 0x0f, + 0x26, 0x9a, 0x18, 0x6f, 0x1c, 0x38, 0x7a, 0xf1, 0x2f, 0xf0, 0x8a, 0x27, 0x49, 0xbc, 0x78, 0x6a, + 0x0c, 0x78, 0xf0, 0xdc, 0xbf, 0xc0, 0xec, 0xec, 0xcc, 0x76, 0xbb, 0xd4, 0xd2, 0x52, 0xe2, 0xad, + 0x3b, 0xf3, 0x7d, 0xef, 0x7d, 0xdf, 0x7b, 0x8f, 0x37, 0x40, 0x31, 0x83, 0x49, 0xde, 0x20, 0x0a, + 0x29, 0xa5, 0x89, 0xa9, 0xad, 0x60, 0xa2, 0x94, 0x13, 0xca, 0x6a, 0x09, 0x17, 0xd7, 0x64, 0xb3, + 0x68, 0x58, 0x06, 0x1a, 0x74, 0x00, 0xb2, 0x0b, 0x90, 0xcb, 0x89, 0xd8, 0x90, 0x6e, 0xe8, 0x06, + 0xbd, 0x57, 0xec, 0x5f, 0x0e, 0x34, 0x36, 0xa2, 0x1b, 0x86, 0x9e, 0xc3, 0x8a, 0x66, 0x66, 0x15, + 0xad, 0x50, 0x30, 0x2c, 0xcd, 0xca, 0x1a, 0x05, 0xc2, 0x6e, 0xe3, 0x8d, 0x32, 0xe5, 0x8d, 0x0c, + 0xce, 0x71, 0xc4, 0xc4, 0x8a, 0x41, 0x11, 0x69, 0x8d, 0x60, 0x47, 0x83, 0x52, 0x4e, 0xa4, 0xb1, + 0xa5, 0x25, 0x14, 0x53, 0xd3, 0xb3, 0x05, 0x1a, 0xce, 0xc1, 0x4a, 0xcb, 0xf0, 0xd4, 0x03, 0x1b, + 0xf1, 0x90, 0x47, 0x53, 0xf1, 0x6a, 0x09, 0x13, 0x0b, 0xcd, 0x43, 0x58, 0x03, 0x47, 0x41, 0x1c, + 0x8c, 0x47, 0x92, 0x63, 0xb2, 0x13, 0x59, 0xb6, 0x23, 0xcb, 0x8e, 0x3b, 0x16, 0x59, 0x5e, 0xd2, + 0x74, 0xcc, 0xb8, 0xaa, 0x87, 0x29, 0x6d, 0x03, 0x38, 0xec, 0xcf, 0x40, 0x4c, 0xa3, 0x40, 0x30, + 0x9a, 0x83, 0x61, 0xd7, 0x44, 0x14, 0xc4, 0xbb, 0xc6, 0x23, 0xc9, 0x51, 0xb9, 0x41, 0x99, 0x64, + 0x4e, 0x4d, 0x75, 0xef, 0x54, 0xc4, 0x80, 0x5a, 0x63, 0xa1, 0x85, 0x3a, 0x95, 0x41, 0xaa, 0xf2, + 0xfc, 0xa1, 0x2a, 0x9d, 0xfc, 0x75, 0x32, 0x9f, 0xc1, 0xa1, 0x3a, 0x95, 0xbc, 0x0c, 0x57, 0x61, + 0x84, 0x67, 0x5b, 0xce, 0x66, 0x68, 0x1d, 0xba, 0x53, 0xc3, 0xd5, 0x8a, 0x88, 0xd6, 0xb4, 0x7c, + 0x6e, 0x46, 0xf2, 0x5c, 0x4a, 0x2a, 0xe4, 0x5f, 0x8b, 0x99, 0x99, 0xd0, 0x9b, 0x2d, 0x31, 0xf0, + 0x67, 0x4b, 0x0c, 0x48, 0x4f, 0x7d, 0x25, 0x76, 0xfd, 0xcf, 0xc2, 0x10, 0x27, 0xb0, 0x02, 0xb7, + 0x64, 0xdf, 0x25, 0x49, 0x9f, 0x78, 0x6d, 0x1f, 0x13, 0x5c, 0x5c, 0x28, 0x1a, 0x25, 0x93, 0x74, + 0xaa, 0xdb, 0xd7, 0xf7, 0xe0, 0x91, 0xfb, 0xbe, 0x05, 0xe0, 0xe9, 0x03, 0xda, 0x98, 0xf1, 0x1b, + 0xb0, 0x57, 0xa7, 0x27, 0xac, 0xeb, 0x42, 0x43, 0xdb, 0x2e, 0x91, 0xf9, 0x66, 0x9c, 0xe3, 0xeb, + 0xf9, 0x2b, 0xc0, 0x3a, 0xe3, 0x66, 0xea, 0xb8, 0x7a, 0x32, 0x0c, 0x51, 0x95, 0x36, 0xcb, 0x56, + 0xd6, 0x9f, 0x1a, 0xac, 0x56, 0xc4, 0x01, 0x87, 0xc5, 0x6f, 0x24, 0xb5, 0x8f, 0xfe, 0x5c, 0xcc, + 0x48, 0x8f, 0xfc, 0x0d, 0x74, 0x6b, 0x34, 0x03, 0x7b, 0x28, 0x88, 0x4d, 0x46, 0x6b, 0x25, 0x72, + 0x28, 0xd2, 0x77, 0x00, 0x47, 0xea, 0xc3, 0xde, 0xc3, 0xf9, 0x34, 0x2e, 0x92, 0xff, 0xed, 0xcf, + 0x37, 0x4d, 0x5d, 0x47, 0x9e, 0xa6, 0x4d, 0x00, 0x47, 0xff, 0xe1, 0x88, 0xd5, 0x2b, 0x0a, 0xfb, + 0xf2, 0xce, 0x11, 0x1d, 0xaa, 0xb0, 0xca, 0x3f, 0x8f, 0x6f, 0x5e, 0x5e, 0x03, 0x78, 0xc6, 0x15, + 0xb1, 0x84, 0x8b, 0xf9, 0x2c, 0x21, 0xf6, 0x62, 0xee, 0xb8, 0xaa, 0x67, 0x61, 0x77, 0x89, 0xe0, + 0x22, 0xd5, 0x16, 0x4e, 0x0d, 0x54, 0x2b, 0x62, 0xc4, 0x61, 0xd8, 0xa7, 0x92, 0x4a, 0x2f, 0x3d, + 0x0b, 0xe5, 0x8b, 0xb7, 0xbd, 0x75, 0x3a, 0x58, 0x2d, 0xae, 0xc1, 0x88, 0x59, 0x3b, 0xa6, 0x42, + 0xfa, 0xbd, 0x42, 0x3c, 0x97, 0x92, 0xea, 0x85, 0xa2, 0x27, 0xb0, 0x2f, 0x83, 0x2d, 0x2d, 0x9b, + 0x23, 0xd1, 0x20, 0xfd, 0xd3, 0x3c, 0xd7, 0x70, 0xee, 0x6a, 0x49, 0x6f, 0x53, 0x74, 0x6a, 0xd8, + 0x1e, 0xbf, 0x6a, 0x45, 0x3c, 0xe1, 0x24, 0x60, 0x31, 0x24, 0x95, 0x47, 0x4b, 0x7e, 0x08, 0xc1, + 0x1e, 0xaa, 0x19, 0xbd, 0x05, 0x30, 0xec, 0xbe, 0x05, 0x68, 0xa2, 0x61, 0xfc, 0x86, 0x4f, 0x52, + 0x6c, 0xb2, 0x25, 0xac, 0x53, 0x03, 0x69, 0x6c, 0xf3, 0xc7, 0xef, 0xf7, 0xc1, 0x38, 0x12, 0x94, + 0x46, 0xef, 0x65, 0xed, 0x05, 0xf9, 0x08, 0x60, 0x88, 0xb3, 0xd1, 0x85, 0xc3, 0x33, 0x70, 0x31, + 0x13, 0xad, 0x40, 0x99, 0x96, 0xcb, 0x54, 0x8b, 0x8c, 0xa6, 0x9a, 0x6b, 0x51, 0xd6, 0x3d, 0x13, + 0xb2, 0x81, 0xb6, 0x01, 0x84, 0xb5, 0xe5, 0x89, 0x9a, 0xb8, 0x3f, 0xb0, 0xfe, 0x63, 0x53, 0xad, + 0x81, 0x99, 0xbe, 0xeb, 0x54, 0xdf, 0x15, 0x34, 0xdd, 0x8e, 0x3e, 0x85, 0xad, 0xe3, 0xcf, 0x00, + 0x86, 0xdd, 0x98, 0xcd, 0xfa, 0xe9, 0xdf, 0xb2, 0xb1, 0xc9, 0x96, 0xb0, 0x4c, 0xe3, 0x3c, 0xd5, + 0x78, 0x0b, 0xdd, 0x3c, 0x82, 0x46, 0x65, 0x9d, 0xaf, 0xa6, 0x0d, 0xf4, 0x0d, 0xc0, 0x93, 0xfe, + 0x25, 0x82, 0x12, 0x2d, 0x28, 0xa9, 0x5f, 0xa1, 0xb1, 0x64, 0x3b, 0x14, 0xe6, 0xe1, 0x3e, 0xf5, + 0x70, 0x07, 0xcd, 0x77, 0xe6, 0x41, 0xe1, 0x9b, 0xed, 0x2b, 0x80, 0x03, 0xbe, 0x1d, 0x80, 0x2e, + 0x35, 0xd7, 0x75, 0x70, 0x6d, 0xc5, 0x12, 0x6d, 0x30, 0x98, 0x91, 0x05, 0x6a, 0x64, 0x0e, 0xcd, + 0xb6, 0x65, 0xc4, 0xb3, 0x68, 0x94, 0x75, 0x7b, 0xa7, 0x6d, 0xa4, 0xee, 0xee, 0xec, 0x09, 0x60, + 0x77, 0x4f, 0x00, 0xbf, 0xf6, 0x04, 0xf0, 0x6e, 0x5f, 0x08, 0xec, 0xee, 0x0b, 0x81, 0x9f, 0xfb, + 0x42, 0xe0, 0x79, 0x52, 0xcf, 0x5a, 0x2f, 0x4a, 0x69, 0x79, 0xc5, 0xc8, 0xb3, 0x24, 0x17, 0x73, + 0x5a, 0x9a, 0xf0, 0x84, 0xe5, 0xa4, 0xf2, 0xd2, 0x93, 0xc8, 0x5a, 0x33, 0x31, 0x49, 0xf7, 0xd2, + 0xff, 0x69, 0xa7, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x50, 0x81, 0xfc, 0xb3, 0x8d, 0x0b, 0x00, + 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Subspaces queries all the subspaces inside Desmos + Subspaces(ctx context.Context, in *QuerySubspacesRequest, opts ...grpc.CallOption) (*QuerySubspacesResponse, error) + // Subspace queries all the information about the subspace with the given id + Subspace(ctx context.Context, in *QuerySubspaceRequest, opts ...grpc.CallOption) (*QuerySubspaceResponse, error) + // UserGroups queries all the groups that are present inside the subspace with + // the given id + UserGroups(ctx context.Context, in *QueryUserGroupsRequest, opts ...grpc.CallOption) (*QueryUserGroupsResponse, error) + // UserGroup queries the user group having the given id inside the specific + // subspace + UserGroup(ctx context.Context, in *QueryUserGroupRequest, opts ...grpc.CallOption) (*QueryUserGroupResponse, error) + // UserGroupMembers queries all the members of a given user group + UserGroupMembers(ctx context.Context, in *QueryUserGroupMembersRequest, opts ...grpc.CallOption) (*QueryUserGroupMembersResponse, error) + // UserPermissions queries the permissions for the given user + UserPermissions(ctx context.Context, in *QueryUserPermissionsRequest, opts ...grpc.CallOption) (*QueryUserPermissionsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Subspaces(ctx context.Context, in *QuerySubspacesRequest, opts ...grpc.CallOption) (*QuerySubspacesResponse, error) { + out := new(QuerySubspacesResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Query/Subspaces", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Subspace(ctx context.Context, in *QuerySubspaceRequest, opts ...grpc.CallOption) (*QuerySubspaceResponse, error) { + out := new(QuerySubspaceResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Query/Subspace", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) UserGroups(ctx context.Context, in *QueryUserGroupsRequest, opts ...grpc.CallOption) (*QueryUserGroupsResponse, error) { + out := new(QueryUserGroupsResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Query/UserGroups", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) UserGroup(ctx context.Context, in *QueryUserGroupRequest, opts ...grpc.CallOption) (*QueryUserGroupResponse, error) { + out := new(QueryUserGroupResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Query/UserGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) UserGroupMembers(ctx context.Context, in *QueryUserGroupMembersRequest, opts ...grpc.CallOption) (*QueryUserGroupMembersResponse, error) { + out := new(QueryUserGroupMembersResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Query/UserGroupMembers", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) UserPermissions(ctx context.Context, in *QueryUserPermissionsRequest, opts ...grpc.CallOption) (*QueryUserPermissionsResponse, error) { + out := new(QueryUserPermissionsResponse) + err := c.cc.Invoke(ctx, "/desmos.subspaces.v1.Query/UserPermissions", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Subspaces queries all the subspaces inside Desmos + Subspaces(context.Context, *QuerySubspacesRequest) (*QuerySubspacesResponse, error) + // Subspace queries all the information about the subspace with the given id + Subspace(context.Context, *QuerySubspaceRequest) (*QuerySubspaceResponse, error) + // UserGroups queries all the groups that are present inside the subspace with + // the given id + UserGroups(context.Context, *QueryUserGroupsRequest) (*QueryUserGroupsResponse, error) + // UserGroup queries the user group having the given id inside the specific + // subspace + UserGroup(context.Context, *QueryUserGroupRequest) (*QueryUserGroupResponse, error) + // UserGroupMembers queries all the members of a given user group + UserGroupMembers(context.Context, *QueryUserGroupMembersRequest) (*QueryUserGroupMembersResponse, error) + // UserPermissions queries the permissions for the given user + UserPermissions(context.Context, *QueryUserPermissionsRequest) (*QueryUserPermissionsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Subspaces(ctx context.Context, req *QuerySubspacesRequest) (*QuerySubspacesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Subspaces not implemented") +} +func (*UnimplementedQueryServer) Subspace(ctx context.Context, req *QuerySubspaceRequest) (*QuerySubspaceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Subspace not implemented") +} +func (*UnimplementedQueryServer) UserGroups(ctx context.Context, req *QueryUserGroupsRequest) (*QueryUserGroupsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UserGroups not implemented") +} +func (*UnimplementedQueryServer) UserGroup(ctx context.Context, req *QueryUserGroupRequest) (*QueryUserGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UserGroup not implemented") +} +func (*UnimplementedQueryServer) UserGroupMembers(ctx context.Context, req *QueryUserGroupMembersRequest) (*QueryUserGroupMembersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UserGroupMembers not implemented") +} +func (*UnimplementedQueryServer) UserPermissions(ctx context.Context, req *QueryUserPermissionsRequest) (*QueryUserPermissionsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UserPermissions not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Subspaces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QuerySubspacesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Subspaces(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Query/Subspaces", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Subspaces(ctx, req.(*QuerySubspacesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Subspace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QuerySubspaceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Subspace(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Query/Subspace", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Subspace(ctx, req.(*QuerySubspaceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_UserGroups_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryUserGroupsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).UserGroups(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Query/UserGroups", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).UserGroups(ctx, req.(*QueryUserGroupsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_UserGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryUserGroupRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).UserGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Query/UserGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).UserGroup(ctx, req.(*QueryUserGroupRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_UserGroupMembers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryUserGroupMembersRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).UserGroupMembers(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Query/UserGroupMembers", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).UserGroupMembers(ctx, req.(*QueryUserGroupMembersRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_UserPermissions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryUserPermissionsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).UserPermissions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.subspaces.v1.Query/UserPermissions", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).UserPermissions(ctx, req.(*QueryUserPermissionsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "desmos.subspaces.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Subspaces", + Handler: _Query_Subspaces_Handler, + }, + { + MethodName: "Subspace", + Handler: _Query_Subspace_Handler, + }, + { + MethodName: "UserGroups", + Handler: _Query_UserGroups_Handler, + }, + { + MethodName: "UserGroup", + Handler: _Query_UserGroup_Handler, + }, + { + MethodName: "UserGroupMembers", + Handler: _Query_UserGroupMembers_Handler, + }, + { + MethodName: "UserPermissions", + Handler: _Query_UserPermissions_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "desmos/subspaces/v1/query.proto", +} + +func (m *QuerySubspacesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySubspacesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySubspacesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QuerySubspacesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySubspacesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySubspacesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Subspaces) > 0 { + for iNdEx := len(m.Subspaces) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Subspaces[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QuerySubspaceRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySubspaceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySubspaceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.SubspaceId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.SubspaceId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QuerySubspaceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySubspaceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySubspaceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Subspace.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryUserGroupsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUserGroupsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUserGroupsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.SubspaceId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.SubspaceId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryUserGroupsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUserGroupsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUserGroupsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Groups) > 0 { + for iNdEx := len(m.Groups) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Groups[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryUserGroupRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUserGroupRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUserGroupRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.GroupId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x10 + } + if m.SubspaceId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.SubspaceId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryUserGroupResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUserGroupResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUserGroupResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Group.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryUserGroupMembersRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUserGroupMembersRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUserGroupMembersRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.GroupId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x10 + } + if m.SubspaceId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.SubspaceId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryUserGroupMembersResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUserGroupMembersResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUserGroupMembersResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Members) > 0 { + for iNdEx := len(m.Members) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Members[iNdEx]) + copy(dAtA[i:], m.Members[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Members[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryUserPermissionsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUserPermissionsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUserPermissionsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.User) > 0 { + i -= len(m.User) + copy(dAtA[i:], m.User) + i = encodeVarintQuery(dAtA, i, uint64(len(m.User))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.SubspaceId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryUserPermissionsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUserPermissionsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUserPermissionsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Details) > 0 { + for iNdEx := len(m.Details) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Details[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Permissions != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Permissions)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QuerySubspacesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QuerySubspacesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Subspaces) > 0 { + for _, e := range m.Subspaces { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QuerySubspaceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceId != 0 { + n += 1 + sovQuery(uint64(m.SubspaceId)) + } + return n +} + +func (m *QuerySubspaceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Subspace.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryUserGroupsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceId != 0 { + n += 1 + sovQuery(uint64(m.SubspaceId)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryUserGroupsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Groups) > 0 { + for _, e := range m.Groups { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryUserGroupRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceId != 0 { + n += 1 + sovQuery(uint64(m.SubspaceId)) + } + if m.GroupId != 0 { + n += 1 + sovQuery(uint64(m.GroupId)) + } + return n +} + +func (m *QueryUserGroupResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Group.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryUserGroupMembersRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceId != 0 { + n += 1 + sovQuery(uint64(m.SubspaceId)) + } + if m.GroupId != 0 { + n += 1 + sovQuery(uint64(m.GroupId)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryUserGroupMembersResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Members) > 0 { + for _, s := range m.Members { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryUserPermissionsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceId != 0 { + n += 1 + sovQuery(uint64(m.SubspaceId)) + } + l = len(m.User) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryUserPermissionsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Permissions != 0 { + n += 1 + sovQuery(uint64(m.Permissions)) + } + if len(m.Details) > 0 { + for _, e := range m.Details { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QuerySubspacesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySubspacesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySubspacesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QuerySubspacesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySubspacesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySubspacesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subspaces", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Subspaces = append(m.Subspaces, Subspace{}) + if err := m.Subspaces[len(m.Subspaces)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QuerySubspaceRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySubspaceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySubspaceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceId", wireType) + } + m.SubspaceId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QuerySubspaceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySubspaceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySubspaceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Subspace.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUserGroupsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUserGroupsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUserGroupsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceId", wireType) + } + m.SubspaceId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUserGroupsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUserGroupsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUserGroupsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Groups", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Groups = append(m.Groups, UserGroup{}) + if err := m.Groups[len(m.Groups)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUserGroupRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUserGroupRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUserGroupRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceId", wireType) + } + m.SubspaceId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUserGroupResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUserGroupResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUserGroupResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Group.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUserGroupMembersRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUserGroupMembersRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUserGroupMembersRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceId", wireType) + } + m.SubspaceId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUserGroupMembersResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUserGroupMembersResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUserGroupMembersResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Members = append(m.Members, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUserPermissionsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUserPermissionsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUserPermissionsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceId", wireType) + } + m.SubspaceId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.User = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUserPermissionsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUserPermissionsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUserPermissionsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) + } + m.Permissions = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Permissions |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Details", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Details = append(m.Details, PermissionDetail{}) + if err := m.Details[len(m.Details)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/subspaces/types/query.pb.gw.go b/x/subspaces/types/query.pb.gw.go new file mode 100644 index 0000000000..9970076688 --- /dev/null +++ b/x/subspaces/types/query.pb.gw.go @@ -0,0 +1,758 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: desmos/subspaces/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage + +var ( + filter_Query_Subspaces_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_Subspaces_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySubspacesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Subspaces_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Subspaces(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Subspaces_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySubspacesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Subspaces_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Subspaces(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Subspace_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySubspaceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + msg, err := client.Subspace(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Subspace_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySubspaceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + msg, err := server.Subspace(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_UserGroups_0 = &utilities.DoubleArray{Encoding: map[string]int{"subspace_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_UserGroups_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUserGroupsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_UserGroups_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.UserGroups(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_UserGroups_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUserGroupsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_UserGroups_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.UserGroups(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_UserGroup_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUserGroupRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint32(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + msg, err := client.UserGroup(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_UserGroup_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUserGroupRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint32(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + msg, err := server.UserGroup(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_UserGroupMembers_0 = &utilities.DoubleArray{Encoding: map[string]int{"subspace_id": 0, "group_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_Query_UserGroupMembers_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUserGroupMembersRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint32(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_UserGroupMembers_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.UserGroupMembers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_UserGroupMembers_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUserGroupMembersRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint32(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_UserGroupMembers_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.UserGroupMembers(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_UserPermissions_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUserPermissionsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + val, ok = pathParams["user"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "user") + } + + protoReq.User, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "user", err) + } + + msg, err := client.UserPermissions(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_UserPermissions_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUserPermissionsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + val, ok = pathParams["user"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "user") + } + + protoReq.User, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "user", err) + } + + msg, err := server.UserPermissions(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Subspaces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Subspaces_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Subspaces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Subspace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Subspace_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Subspace_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UserGroups_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_UserGroups_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UserGroups_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UserGroup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_UserGroup_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UserGroup_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UserGroupMembers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_UserGroupMembers_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UserGroupMembers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UserPermissions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_UserPermissions_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UserPermissions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Subspaces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Subspaces_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Subspaces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Subspace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Subspace_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Subspace_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UserGroups_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_UserGroups_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UserGroups_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UserGroup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_UserGroup_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UserGroup_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UserGroupMembers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_UserGroupMembers_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UserGroupMembers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UserPermissions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_UserPermissions_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UserPermissions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Subspaces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1}, []string{"desmos", "subspaces", "v1"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Subspace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1, 1, 0, 4, 1, 5, 3}, []string{"desmos", "subspaces", "v1", "subspace_id"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_UserGroups_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"desmos", "subspaces", "v1", "subspace_id", "groups"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_UserGroup_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"desmos", "subspaces", "v1", "subspace_id", "groups", "group_id"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_UserGroupMembers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"desmos", "subspaces", "v1", "subspace_id", "groups", "group_id", "members"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_UserPermissions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"desmos", "subspaces", "v1", "subspace_id", "permissions", "user"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_Subspaces_0 = runtime.ForwardResponseMessage + + forward_Query_Subspace_0 = runtime.ForwardResponseMessage + + forward_Query_UserGroups_0 = runtime.ForwardResponseMessage + + forward_Query_UserGroup_0 = runtime.ForwardResponseMessage + + forward_Query_UserGroupMembers_0 = runtime.ForwardResponseMessage + + forward_Query_UserPermissions_0 = runtime.ForwardResponseMessage +)