diff --git a/.changelog/unreleased/improvements/associate-registry-class.md b/.changelog/unreleased/improvements/associate-registry-class.md new file mode 100644 index 0000000000..92df6bd4c2 --- /dev/null +++ b/.changelog/unreleased/improvements/associate-registry-class.md @@ -0,0 +1,4 @@ +* Add `MsgAssociateRegistryClass` to the registry module, allowing an existing legacy registry + entry to be upgraded to use a registry class without modifying roles. Authorization accepts any + of: CONTROLLER role address, scope data-owner party (for Provenance Metadata Scopes), or NFT + owner — neither takes precedence. diff --git a/proto/provenance/registry/v1/authorization.proto b/proto/provenance/registry/v1/authorization.proto new file mode 100644 index 0000000000..338c8cf8f5 --- /dev/null +++ b/proto/provenance/registry/v1/authorization.proto @@ -0,0 +1,150 @@ +syntax = "proto3"; +package provenance.registry.v1; + +option go_package = "github.com/provenance-io/provenance/x/registry/types"; +option java_package = "io.provenance.registry.v1"; +option java_multiple_files = true; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "provenance/registry/v1/registry.proto"; + +// RegistryClass provides asset class-level authorization over role updates. +// It defines authorization rules for an entire NFT collection (asset class), allowing the +// maintainer to establish custom role update policies without requiring governance proposals. +message RegistryClass { + // registry_class_id is the unique identifier for this registry class (e.g. "loan-registry-v1"). + // It is required since NFT classes do not have an inherent owner, and must be unique across + // all registry classes. + string registry_class_id = 1 [(gogoproto.jsontag) = "registryClassId,omitempty"]; + + // asset_class_id is the Scope Specification ID or NFT Class ID this registry class governs. + string asset_class_id = 2; + + // maintainer is the address authorized to manage this registry class. It is permanent and + // cannot be changed once set. + string maintainer = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // role_authorizations are the authorization rules for role updates within this asset class. + repeated RoleAuthorization role_authorizations = 4 [(gogoproto.nullable) = false]; +} + +// SignatureType defines how signature requirements are evaluated. +enum SignatureType { + // SIGNATURE_TYPE_UNSPECIFIED is the default/unset value. + SIGNATURE_TYPE_UNSPECIFIED = 0; + // SIGNATURE_TYPE_REQUIRED_ALL requires signatures from ALL listed roles. + // Fails immediately if any role does not exist in the registry or NFT state. + SIGNATURE_TYPE_REQUIRED_ALL = 1; + // SIGNATURE_TYPE_REQUIRED_ALL_IF_SET requires signatures from ALL listed roles, + // but only if they exist. Roles that are not set are silently skipped. + SIGNATURE_TYPE_REQUIRED_ALL_IF_SET = 2; + // SIGNATURE_TYPE_REQUIRED_ANY requires a signature from AT LEAST ONE of the listed roles. + // Fails if none of the roles exist. + SIGNATURE_TYPE_REQUIRED_ANY = 3; + // SIGNATURE_TYPE_REQUIRED_ANY_IF_SET requires a signature from AT LEAST ONE of the listed roles, + // but only if any of them exist. Skips the entire requirement if none of the roles are set. + SIGNATURE_TYPE_REQUIRED_ANY_IF_SET = 4; +} + +// NftRole identifies roles managed outside the registry module (e.g., by the metadata module). +// These roles are read-only from the registry module's perspective. +enum NftRole { + // NFT_ROLE_UNSPECIFIED is the default/unset value. + NFT_ROLE_UNSPECIFIED = 0; + // NFT_ROLE_NFT_OWNER is the owner of the NFT. + // For metadata-scope NFTs, this is the scope value owner; otherwise it's the owner from the x/nft module. + NFT_ROLE_NFT_OWNER = 1; +} + +// Assignment describes which address(es) to resolve for a role in an authorization check. +enum Assignment { + // ASSIGNMENT_UNSPECIFIED is the default/unset value. + ASSIGNMENT_UNSPECIFIED = 0; + // ASSIGNMENT_CURRENT resolves exactly one address currently assigned to the role. + // Fails if the role has multiple addresses assigned. + ASSIGNMENT_CURRENT = 1; + // ASSIGNMENT_CURRENT_ALL resolves all addresses currently assigned to the role. + // All of them must sign. + ASSIGNMENT_CURRENT_ALL = 2; + // ASSIGNMENT_CURRENT_ANY resolves any one of the addresses currently assigned to the role. + // At least one must sign. + ASSIGNMENT_CURRENT_ANY = 3; + // ASSIGNMENT_NEW resolves exactly one new address being assigned to the role. + // Fails if multiple new addresses are provided. + // Invalid for NftRole (read-only from registry perspective). + ASSIGNMENT_NEW = 4; + // ASSIGNMENT_NEW_ANY resolves any one of the new addresses being assigned to the role. + // Invalid for NftRole. + ASSIGNMENT_NEW_ANY = 5; + // ASSIGNMENT_NEW_ALL resolves all new addresses being assigned to the role. + // All of them must sign. + // Invalid for NftRole. + ASSIGNMENT_NEW_ALL = 6; +} + +// RoleAuthorization configures who must sign to update a specific role. +// Contains one or more Authorization paths; the update is approved if ANY path is fully satisfied. +message RoleAuthorization { + // role is the registry role whose assignments are being controlled. + RegistryRole role = 1; + + // authorizations is a list of alternative approval paths. + // The role update is approved if any single authorization is fully satisfied. + repeated Authorization authorizations = 2; +} + +// Authorization defines one complete approval path for a role update. +// All signature requirements in this authorization must be satisfied for this path to succeed. +message Authorization { + // description is a human-readable explanation of this authorization path. + string description = 1; + + // signatures is the ordered list of signature requirements that must all be satisfied. + repeated SignatureRequirement signatures = 2; +} + +// SignatureRequirement defines a single signature check within an authorization path. +message SignatureRequirement { + // type controls how the roles are evaluated (required_all, required_all_if_set, etc.). + SignatureType type = 1; + + // roles lists the role assignments that must be checked. + repeated RoleAssignment roles = 2; +} + +// RoleAssignment specifies which role and which assignment type to resolve for a signature check. +message RoleAssignment { + // role_selector identifies the role to resolve, either a single role or a priority list. + oneof role_selector { + // registry_role is a role managed within the registry module state. + // Can be used with any assignment type. + RegistryRole registry_role = 1; + // nft_role is a role managed by another module (e.g., NFT_ROLE_NFT_OWNER from metadata). + // Can only be used with ASSIGNMENT_CURRENT* variants. + NftRole nft_role = 2; + // role_priority is an ordered list of roles; the first one that exists is used. + RolePriority role_priority = 3; + } + + // assignment specifies which address(es) to resolve for the role. + Assignment assignment = 4; +} + +// RolePriority is an ordered list of role entries used for fallback/hierarchical authority. +// The keeper uses the first role in the list that exists. +message RolePriority { + // entries is the ordered list of roles to check. The first existing role is used. + repeated RolePriorityEntry entries = 1; +} + +// RolePriorityEntry is a single entry in a RolePriority list. +message RolePriorityEntry { + // role identifies the role in this priority slot. + oneof role { + // registry_role is a role managed within the registry module state. + RegistryRole registry_role = 1; + // nft_role is a role managed by another module. + NftRole nft_role = 2; + } +} diff --git a/proto/provenance/registry/v1/events.proto b/proto/provenance/registry/v1/events.proto index 0669c2d07b..c5f0aaf181 100644 --- a/proto/provenance/registry/v1/events.proto +++ b/proto/provenance/registry/v1/events.proto @@ -5,6 +5,8 @@ option go_package = "github.com/provenance-io/provenance/x/registry/typ option java_package = "io.provenance.registry.v1"; option java_multiple_files = true; +import "gogoproto/gogo.proto"; + // EventNFTRegistered is the event emitted when a registry is created for an NFT. message EventNFTRegistered { string nft_id = 1; @@ -38,3 +40,77 @@ message EventRegistryBulkUpdated { string nft_id = 1; string asset_class_id = 2; } + +// EventRoleChangeProposed is emitted when a pending role change is opened. +message EventRoleChangeProposed { + string nft_id = 1; + string asset_class_id = 2; + string change_id = 3; + string proposer = 4; +} + +// EventRoleChangeApproved is emitted when a party records an approval for a pending role change. +message EventRoleChangeApproved { + string change_id = 1; + string approver = 2; +} + +// EventRoleChangeApplied is emitted when a pending role change accumulates enough approvals and is applied. +message EventRoleChangeApplied { + string nft_id = 1; + string asset_class_id = 2; + string change_id = 3; +} + +// EventRoleChangeCancelled is emitted when a pending role change is cancelled by its proposer. +message EventRoleChangeCancelled { + string change_id = 1; + string cancelled_by = 2; +} + +// EventRegistryClassCreated is emitted when a registry class is created. +message EventRegistryClassCreated { + string registry_class_id = 1; + string asset_class_id = 2; + string maintainer = 3; +} + +// EventRegistryClassUpdated is emitted when a registry class's authorization rules are updated. +message EventRegistryClassUpdated { + string registry_class_id = 1; + string maintainer = 2; +} + +// EventParamsUpdated is emitted when the registry module's params are updated via governance. +message EventParamsUpdated {} + +// RoleSigner describes a role/assignment whose resolved addresses contributed a signature toward +// authorizing a role change. It is the structured form of an entry in EventRoleUpdated.signers. +message RoleSigner { + // role is the (registry or NFT) role whose holders provided the signature(s). + string role = 1; + // assignment is the assignment variant the role was resolved under (e.g. ASSIGNMENT_CURRENT). + string assignment = 2; + // addresses are the resolved addresses for the role that signed to authorize the change. + repeated string addresses = 3; +} + +// EventRoleUpdated is the comprehensive event emitted whenever a role is granted, revoked, or set +// for a registered NFT. It is emitted for MsgGrantRole, MsgRevokeRole, and once per updated role +// for MsgSetRoles (including changes applied via the propose/approve accumulation flow). +message EventRoleUpdated { + // nft_id is the ID of the NFT for which the role was updated. + string nft_id = 1; + // asset_class_id is the ID of the asset class the NFT belongs to. + string asset_class_id = 2; + // registry_class_id is the registry class governing this NFT (empty if none). + string registry_class_id = 3; + // role is the role that was updated. + string role = 4; + // addresses are the addresses assigned to the role after this operation (empty if cleared). + repeated string addresses = 5; + // previous_addresses are the addresses assigned to the role before this operation. + repeated string previous_addresses = 6; + // signers describes the roles/addresses that authorized this change. + repeated RoleSigner signers = 7 [(gogoproto.nullable) = false]; +} diff --git a/proto/provenance/registry/v1/genesis.proto b/proto/provenance/registry/v1/genesis.proto index 7aa4c76c28..dd282836ab 100644 --- a/proto/provenance/registry/v1/genesis.proto +++ b/proto/provenance/registry/v1/genesis.proto @@ -7,6 +7,8 @@ option java_multiple_files = true; import "gogoproto/gogo.proto"; import "provenance/registry/v1/registry.proto"; +import "provenance/registry/v1/authorization.proto"; +import "provenance/registry/v1/params.proto"; // GenesisState defines the registry module's genesis state. // This contains all the registry entries that exist when the blockchain is first initialized. @@ -14,4 +16,14 @@ message GenesisState { // entries is the list of registry entries. // These entries define the initial state of the registry module. repeated RegistryEntry entries = 1 [(gogoproto.nullable) = false]; + + // pending_role_changes is the list of role changes awaiting approval. + // These preserve in-flight multi-party role changes across genesis export/import. + repeated PendingRoleChange pending_role_changes = 2 [(gogoproto.nullable) = false]; + + // registry_classes is the list of registry classes defining asset class-level authorization rules. + repeated RegistryClass registry_classes = 3 [(gogoproto.nullable) = false]; + + // params defines the registry module parameters at genesis. + Params params = 4 [(gogoproto.nullable) = false]; } \ No newline at end of file diff --git a/proto/provenance/registry/v1/params.proto b/proto/provenance/registry/v1/params.proto new file mode 100644 index 0000000000..17d1d4ec63 --- /dev/null +++ b/proto/provenance/registry/v1/params.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; +package provenance.registry.v1; + +option go_package = "github.com/provenance-io/provenance/x/registry/types"; +option java_package = "io.provenance.registry.v1"; +option java_multiple_files = true; + +import "gogoproto/gogo.proto"; +import "provenance/registry/v1/authorization.proto"; +import "google/protobuf/duration.proto"; + +// Params defines the registry module's parameters. +message Params { + // role_authorizations are the default authorization policies that govern role updates for + // registry entries that are not associated with a registry class. They form the middle tier of + // the two-tier resolution: a registry class policy takes precedence, then these module defaults, + // and finally roles without any policy fall back to legacy NFT-owner authorization. + repeated RoleAuthorization role_authorizations = 1 [(gogoproto.nullable) = false]; + + // pending_change_expiry is how long a pending role change remains valid after it is proposed. + // Approvals received after the expiry are rejected and the change is cleaned up. + // Zero value (default) means pending changes never expire. + google.protobuf.Duration pending_change_expiry = 2 + [(gogoproto.stdduration) = true, (gogoproto.nullable) = false]; +} diff --git a/proto/provenance/registry/v1/query.proto b/proto/provenance/registry/v1/query.proto index 77b4c6add9..7c542228d4 100644 --- a/proto/provenance/registry/v1/query.proto +++ b/proto/provenance/registry/v1/query.proto @@ -9,6 +9,8 @@ import "cosmos/base/query/v1beta1/pagination.proto"; import "gogoproto/gogo.proto"; import "google/api/annotations.proto"; import "provenance/registry/v1/registry.proto"; +import "provenance/registry/v1/authorization.proto"; +import "provenance/registry/v1/params.proto"; // Query defines the gRPC querier service for the registry module. // This service provides read-only access to registry data and role verification. @@ -30,6 +32,44 @@ service Query { option (google.api.http).get = "/provenance/registry/v1/has_role/{key.asset_class_id}/{key.nft_id}/{address}/{role}"; } + + // PendingRoleChange returns a single pending role change by its id. + rpc PendingRoleChange(QueryPendingRoleChangeRequest) returns (QueryPendingRoleChangeResponse) { + option (google.api.http).get = "/provenance/registry/v1/pending_role_change/{id}"; + } + + // PendingRoleChanges returns the pending role changes, optionally filtered by registry key. + rpc PendingRoleChanges(QueryPendingRoleChangesRequest) returns (QueryPendingRoleChangesResponse) { + option (google.api.http).get = "/provenance/registry/v1/pending_role_changes"; + } + + // RegistryClass returns a single registry class (including its authorization policy) by id. + rpc RegistryClass(QueryRegistryClassRequest) returns (QueryRegistryClassResponse) { + option (google.api.http).get = "/provenance/registry/v1/registry_class/{registry_class_id}"; + } + + // RegistryClasses returns all registry classes. + rpc RegistryClasses(QueryRegistryClassesRequest) returns (QueryRegistryClassesResponse) { + option (google.api.http).get = "/provenance/registry/v1/registry_classes"; + } + + // Params returns the registry module parameters, including the default role authorization + // policies. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/provenance/registry/v1/params"; + } + + // ValidateRoleChange performs a read-only dry-run of a role-change batch, reporting whether the + // supplied approvers would satisfy every affected role's authorization policy without writing + // any state. + rpc ValidateRoleChange(QueryValidateRoleChangeRequest) returns (QueryValidateRoleChangeResponse) { + // This is a read-only query, but it is exposed over POST because the request carries the full + // role_updates and approvers lists, which cannot be supplied via a GET query string. + option (google.api.http) = { + post: "/provenance/registry/v1/validate_role_change" + body: "*" + }; + } } // QueryGetRegistryRequest is the request type for the Query/GetRegistry RPC method. @@ -92,3 +132,95 @@ message QueryHasRoleResponse { // This boolean value indicates whether the role verification was successful. bool has_role = 1; } + +// QueryPendingRoleChangeRequest is the request type for the Query/PendingRoleChange RPC method. +message QueryPendingRoleChangeRequest { + // id is the deterministic identifier of the pending role change to retrieve. + string id = 1; +} + +// QueryPendingRoleChangeResponse is the response type for the Query/PendingRoleChange RPC method. +message QueryPendingRoleChangeResponse { + // pending_role_change is the pending role change for the requested id. + PendingRoleChange pending_role_change = 1 [(gogoproto.nullable) = false]; +} + +// QueryPendingRoleChangesRequest is the paginated request type for the Query/PendingRoleChanges +// RPC method. +message QueryPendingRoleChangesRequest { + // key optionally filters the results to a single registry entry. When unset, all pending role + // changes are returned. + RegistryKey key = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 99; +} + +// QueryPendingRoleChangesResponse is the paginated response type for the Query/PendingRoleChanges +// RPC method. +message QueryPendingRoleChangesResponse { + // pending_role_changes is the collection of pending role changes. + repeated PendingRoleChange pending_role_changes = 1 [(gogoproto.nullable) = false]; + + // pagination is the pagination details for this response. + cosmos.base.query.v1beta1.PageResponse pagination = 99; +} + +// QueryRegistryClassRequest is the request type for the Query/RegistryClass RPC method. +message QueryRegistryClassRequest { + // registry_class_id is the unique identifier of the registry class to retrieve. + string registry_class_id = 1; +} + +// QueryRegistryClassResponse is the response type for the Query/RegistryClass RPC method. +message QueryRegistryClassResponse { + // registry_class is the registry class for the requested id, including its authorization policy. + RegistryClass registry_class = 1 [(gogoproto.nullable) = false]; +} + +// QueryRegistryClassesRequest is the paginated request type for the Query/RegistryClasses RPC method. +message QueryRegistryClassesRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 99; +} + +// QueryRegistryClassesResponse is the paginated response type for the Query/RegistryClasses RPC method. +message QueryRegistryClassesResponse { + // registry_classes is the collection of registry classes. + repeated RegistryClass registry_classes = 1 [(gogoproto.nullable) = false]; + + // pagination is the pagination details for this response. + cosmos.base.query.v1beta1.PageResponse pagination = 99; +} + +// QueryParamsRequest is the request type for the Query/Params RPC method. +message QueryParamsRequest {} + +// QueryParamsResponse is the response type for the Query/Params RPC method. +message QueryParamsResponse { + // params are the current registry module parameters. + Params params = 1 [(gogoproto.nullable) = false]; +} + +// QueryValidateRoleChangeRequest is the request type for the Query/ValidateRoleChange RPC method. +// It describes a candidate role-change batch and the set of approvers to test against each affected +// role's authorization policy. +message QueryValidateRoleChangeRequest { + // key identifies the registry entry the role change targets. + RegistryKey key = 1; + + // role_updates is the desired-state batch to evaluate (same shape as MsgSetRoles). + repeated RoleUpdate role_updates = 2 [(gogoproto.nullable) = false]; + + // approvers is the accumulated/candidate set of approver addresses to test. + repeated string approvers = 3; +} + +// QueryValidateRoleChangeResponse is the response type for the Query/ValidateRoleChange RPC method. +message QueryValidateRoleChangeResponse { + // error contains the authorization failure explanation. It is empty when the change is authorized. + string error = 1; + + // authorized is true if the supplied approvers satisfy every affected role's policy. + bool authorized = 2; +} diff --git a/proto/provenance/registry/v1/registry.proto b/proto/provenance/registry/v1/registry.proto index f52119ab40..5278d81875 100644 --- a/proto/provenance/registry/v1/registry.proto +++ b/proto/provenance/registry/v1/registry.proto @@ -7,6 +7,7 @@ option java_multiple_files = true; import "gogoproto/gogo.proto"; import "cosmos_proto/cosmos.proto"; +import "google/protobuf/timestamp.proto"; // RegistryRole defines the different types of roles that can be assigned to addresses. // These roles determine the permissions and capabilities that an address has within the registry system. @@ -32,6 +33,17 @@ enum RegistryRole { // REGISTRY_ROLE_ORIGINATOR indicates the address has originator privileges. // Originators are responsible for creating and originating the underlying assets. REGISTRY_ROLE_ORIGINATOR = 6; + // REGISTRY_ROLE_LIEN_OWNER indicates the entity on whose behalf the registry acts as a nominal lien holder. + REGISTRY_ROLE_LIEN_OWNER = 7; + // REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN indicates an organization with a security interest in the lien. + // This party can foreclose into the Lien Owner role or direct a transfer in case of default. + REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN = 8; + // REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE indicates an organization with a financial interest in the eNote. + // This party can foreclose into the Controller role or direct a transfer in case of default. + REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE = 9; + // REGISTRY_ROLE_PLEDGEE indicates a lender or creditor that holds a security interest in pledged loans + // as collateral securing an obligation of the Pledgor. + REGISTRY_ROLE_PLEDGEE = 10; } // RegistryKey represents a unique identifier for registry entries. @@ -61,6 +73,12 @@ message RegistryEntry { // roles is a list of roles and addresses that can perform that role. // Each role entry contains a role type and the addresses authorized for that role. repeated RolesEntry roles = 2 [(gogoproto.nullable) = false]; + + // registry_class_id is the ID of the registry class governing this entry's authorization rules. + // If set, role updates for this entry use the authorization rules defined in the referenced + // registry class. If empty, role updates fall back to the module params default policies, and + // then to legacy NFT owner authorization for any role with no policy. + string registry_class_id = 3 [(gogoproto.jsontag) = "registryClassId,omitempty"]; } // RolesEntry represents a mapping between a role and the addresses that can perform that role. @@ -72,4 +90,42 @@ message RolesEntry { // addresses is the list of blockchain addresses that can perform this role. // These addresses have the permissions associated with the specified role. repeated string addresses = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; +} + +// RoleUpdate specifies the desired set of addresses for a single role. +message RoleUpdate { + // role is the role to update. + RegistryRole role = 1; + + // addresses is the desired set of addresses for this role. + // An empty list means the role should be cleared entirely. + repeated string addresses = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; +} + +// PendingRoleChange is a role change awaiting the approvals required by the affected roles' +// authorization policies. Each required party submits a single-signer approval; once the +// accumulated approvers satisfy every affected role's policy, the change is applied atomically +// and this record is removed. +message PendingRoleChange { + // id is the deterministic identifier of this pending change + // (a hash of key + the sorted set of role updates). + string id = 1; + + // key identifies the registry entry the change applies to. + RegistryKey key = 2; + + // role_updates is the desired state for each role the change will set when applied. The same + // desired-state, multi-role semantics as MsgSetRoles, collected through accumulated approvals. + repeated RoleUpdate role_updates = 3 [(gogoproto.nullable) = false]; + + // proposer is the address that opened the pending change. + string proposer = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // approvals is the accumulated set of addresses that have approved this change. + repeated string approvals = 5 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // expires_at is the block time after which this pending change is no longer valid. + // Zero value means no expiry. + google.protobuf.Timestamp expires_at = 6 + [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; } \ No newline at end of file diff --git a/proto/provenance/registry/v1/tx.proto b/proto/provenance/registry/v1/tx.proto index fb26230b5f..9a7d24d2c6 100644 --- a/proto/provenance/registry/v1/tx.proto +++ b/proto/provenance/registry/v1/tx.proto @@ -9,6 +9,8 @@ import "gogoproto/gogo.proto"; import "cosmos_proto/cosmos.proto"; import "cosmos/msg/v1/msg.proto"; import "provenance/registry/v1/registry.proto"; +import "provenance/registry/v1/authorization.proto"; +import "provenance/registry/v1/params.proto"; // Msg defines the registry Msg service. // This service provides transaction functionality for managing registry entries and roles. @@ -21,10 +23,14 @@ service Msg { // GrantRole grants a role to one or more addresses. // This adds the specified addresses to the role for the given registry key. + // The single signer must satisfy the role's authorization policy directly; multi-party role + // changes are made through ProposeRoleChange / ApproveRoleChange. rpc GrantRole(MsgGrantRole) returns (MsgGrantRoleResponse); // RevokeRole revokes a role from one or more addresses. // This removes the specified addresses from the role for the given registry key. + // The single signer must satisfy the role's authorization policy directly; multi-party role + // changes are made through ProposeRoleChange / ApproveRoleChange. rpc RevokeRole(MsgRevokeRole) returns (MsgRevokeRoleResponse); // UnregisterNFT unregisters an NFT from the registry. @@ -35,6 +41,42 @@ service Msg { // This creates multiple registry entries, or updates if one exists. // Each registry in this will cost one MsgRegisterNFT. rpc RegistryBulkUpdate(MsgRegistryBulkUpdate) returns (MsgRegistryBulkUpdateResponse); + + // SetRoles atomically sets the desired state for one or more roles on a registry entry. + // The single signer must satisfy each affected role's authorization policy directly; multi-party + // role changes are made through ProposeRoleChange / ApproveRoleChange. + rpc SetRoles(MsgSetRoles) returns (MsgSetRolesResponse); + + // ProposeRoleChange opens a pending role change that accumulates single-signer approvals. + // The change auto-applies once the role's authorization policy is satisfied. + rpc ProposeRoleChange(MsgProposeRoleChange) returns (MsgProposeRoleChangeResponse); + + // ApproveRoleChange records a single-signer approval for an open pending role change. + // When the accumulated approvals satisfy the role's policy, the change is applied automatically. + rpc ApproveRoleChange(MsgApproveRoleChange) returns (MsgApproveRoleChangeResponse); + + // CreateRegistryClass creates a new registry class that defines asset class-level authorization + // rules for role updates. The signer must match the maintainer address. + rpc CreateRegistryClass(MsgCreateRegistryClass) returns (MsgCreateRegistryClassResponse); + + // UpdateRegistryClassRoleAuthorization replaces the authorization rules for an existing registry + // class. Only the current maintainer may update the rules. + rpc UpdateRegistryClassRoleAuthorization(MsgUpdateRegistryClassRoleAuthorization) + returns (MsgUpdateRegistryClassRoleAuthorizationResponse); + + // CancelRoleChange cancels an open pending role change. + // Only the original proposer may cancel. + rpc CancelRoleChange(MsgCancelRoleChange) returns (MsgCancelRoleChangeResponse); + + // AssociateRegistryClass associates or updates the registry class for an existing registry entry + // without modifying any roles. The signer must be the CONTROLLER if one is set, or the scope + // data owner if the NFT is a Provenance Metadata Scope, or the NFT owner otherwise. + rpc AssociateRegistryClass(MsgAssociateRegistryClass) returns (MsgAssociateRegistryClassResponse); + + // UpdateParams is a governance proposal endpoint for updating the registry module's params, + // including the default role authorization policies. The authority must be the governance module + // account address. + rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); } // MsgRegisterNFT represents a message to register a new NFT in the registry. @@ -53,6 +95,10 @@ message MsgRegisterNFT { // roles is a list of roles and addresses that can perform that role. // Each role entry defines a role type and the addresses authorized for that role. repeated RolesEntry roles = 3 [(gogoproto.nullable) = false]; + + // registry_class_id optionally associates the new registry entry with a registry class whose + // authorization rules govern subsequent role updates. If set, the referenced class must exist. + string registry_class_id = 4 [(gogoproto.jsontag) = "registryClassId,omitempty"]; } // MsgRegisterNFTResponse defines the response for RegisterNFT. @@ -64,8 +110,9 @@ message MsgRegisterNFTResponse {} message MsgGrantRole { option (cosmos.msg.v1.signer) = "signer"; - // signer is the address that is authorized to grant the role. - // This address must have the appropriate permissions to modify role assignments. + // signer is the address authorizing the role grant. The signer must satisfy the role's + // authorization policy on its own (e.g. the NFT owner for roles without a policy). Multi-party + // role changes are made through ProposeRoleChange / ApproveRoleChange instead. string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // key is the registry key to grant the role to. @@ -90,8 +137,9 @@ message MsgGrantRoleResponse {} message MsgRevokeRole { option (cosmos.msg.v1.signer) = "signer"; - // signer is the address that is authorized to revoke the role. - // This address must have the appropriate permissions to modify role assignments. + // signer is the address authorizing the role revocation. The signer must satisfy the role's + // authorization policy on its own (e.g. the NFT owner for roles without a policy). Multi-party + // role changes are made through ProposeRoleChange / ApproveRoleChange instead. string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // key is the registry key to revoke the role from. @@ -145,4 +193,173 @@ message MsgRegistryBulkUpdate { // MsgRegistryBulkUpdateResponse defines the response for RegistryBulkUpdate. // This is an empty response indicating successful bulk update. -message MsgRegistryBulkUpdateResponse {} \ No newline at end of file +message MsgRegistryBulkUpdateResponse {} + +// MsgSetRoles atomically sets the desired state for one or more roles on a registry entry. +// For each role in role_updates, the keeper computes the diff between current and desired +// addresses and applies grants and revokes to reach the desired state. +// All updates succeed or all fail (atomic). +message MsgSetRoles { + option (cosmos.msg.v1.signer) = "signer"; + + // signer is the address authorizing the role updates. The signer must satisfy each affected + // role's authorization policy on its own. Multi-party role changes are made through + // ProposeRoleChange / ApproveRoleChange instead. + string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // key identifies the registry entry to update. + RegistryKey key = 2; + + // role_updates contains the desired state for each role to update. + // At least one entry is required. Roles not listed here are unchanged. + repeated RoleUpdate role_updates = 3 [(gogoproto.nullable) = false]; +} + +// MsgSetRolesResponse defines the response for SetRoles. +message MsgSetRolesResponse {} + +// MsgProposeRoleChange opens a pending role change that collects single-signer approvals until +// every affected role's authorization policy is satisfied, then applies the whole batch +// atomically. Its payload mirrors MsgSetRoles (desired-state, multi-role), but using single-signer +// messages (rather than one multi-signer message) keeps every step compatible with authz delegation. +message MsgProposeRoleChange { + option (cosmos.msg.v1.signer) = "signer"; + + // signer is the address proposing the change. It is recorded as the first approval; it only + // counts toward a policy if the signer is itself a required party. + string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // key identifies the registry entry to change. + RegistryKey key = 2; + + // role_updates contains the desired state for each role to set when the change is applied. + // At least one entry is required. Roles not listed here are unchanged. + repeated RoleUpdate role_updates = 3 [(gogoproto.nullable) = false]; +} + +// MsgProposeRoleChangeResponse defines the response for ProposeRoleChange. +message MsgProposeRoleChangeResponse { + // change_id is the deterministic identifier of the pending change. It is also returned when the + // change auto-applied immediately (e.g. a single-party policy satisfied by the proposer). + string change_id = 1; + + // applied is true if the proposal alone satisfied the policy and the change was applied. + bool applied = 2; +} + +// MsgApproveRoleChange records a single-signer approval for an open pending role change. +message MsgApproveRoleChange { + option (cosmos.msg.v1.signer) = "signer"; + + // signer is the approving party. Single-signer, so it can be delegated via authz. + string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // change_id is the identifier of the pending change to approve. + string change_id = 2; +} + +// MsgApproveRoleChangeResponse defines the response for ApproveRoleChange. +message MsgApproveRoleChangeResponse { + // applied is true if this approval satisfied the policy and the change was applied. + bool applied = 1; +} + +// MsgCancelRoleChange cancels an open pending role change. +// Only the original proposer may cancel. +message MsgCancelRoleChange { + option (cosmos.msg.v1.signer) = "signer"; + + // signer must be the original proposer of the pending change. + string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // change_id is the identifier of the pending change to cancel. + string change_id = 2; +} + +// MsgCancelRoleChangeResponse defines the response for CancelRoleChange. +message MsgCancelRoleChangeResponse {} + +// MsgAssociateRegistryClass associates or updates the registry class for an existing registry +// entry without modifying any roles. This is the upgrade path from legacy (no-class) registration +// to class-governed authorization. +// +// Authorization: the signer must satisfy at least one of the following — neither takes precedence: +// - CONTROLLER: the signer is one of the entry's CONTROLLER role addresses. +// - Scope data owner: if the NFT is a Provenance Metadata Scope, the signer is one of the +// scope's data-owner parties. +// - NFT owner: for all other NFTs, the signer owns the NFT. +message MsgAssociateRegistryClass { + option (cosmos.msg.v1.signer) = "signer"; + + // signer is the address authorizing this association. + string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // key identifies the existing registry entry to update. + RegistryKey key = 2; + + // registry_class_id is the ID of the registry class to associate. Must be non-empty; the + // referenced class must exist and its asset_class_id must match the entry's asset_class_id. + string registry_class_id = 3 [(gogoproto.jsontag) = "registryClassId,omitempty"]; +} + +// MsgAssociateRegistryClassResponse defines the response for AssociateRegistryClass. +message MsgAssociateRegistryClassResponse {} + +// MsgCreateRegistryClass creates a new registry class defining asset class-level authorization +// rules for role updates within an NFT collection. +message MsgCreateRegistryClass { + option (cosmos.msg.v1.signer) = "signer"; + + // signer must match the maintainer address. + string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // registry_class_id is the unique identifier for the registry class. Must be unique across all + // registry classes. + string registry_class_id = 2; + + // asset_class_id is the Scope Specification ID or NFT Class ID this registry class governs. + string asset_class_id = 3; + + // maintainer is the address authorized to manage this registry class. It is permanent and + // cannot be changed after creation. + string maintainer = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // role_authorizations are the initial authorization rules for this asset class. + repeated RoleAuthorization role_authorizations = 5 [(gogoproto.nullable) = false]; +} + +// MsgCreateRegistryClassResponse defines the response for CreateRegistryClass. +message MsgCreateRegistryClassResponse {} + +// MsgUpdateRegistryClassRoleAuthorization replaces the authorization rules for an existing +// registry class. The new rules completely replace the existing rules (not a merge). +message MsgUpdateRegistryClassRoleAuthorization { + option (cosmos.msg.v1.signer) = "signer"; + + // signer must be the current maintainer address. + string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // registry_class_id identifies the registry class to update. + string registry_class_id = 2; + + // role_authorizations are the updated authorization rules (replaces existing rules). + repeated RoleAuthorization role_authorizations = 3 [(gogoproto.nullable) = false]; +} + +// MsgUpdateRegistryClassRoleAuthorizationResponse defines the response for +// UpdateRegistryClassRoleAuthorization. +message MsgUpdateRegistryClassRoleAuthorizationResponse {} + +// MsgUpdateParams is a request to update the registry module's params. +message MsgUpdateParams { + option (cosmos.msg.v1.signer) = "authority"; + + // authority should be the governance module account address. + string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // params are the new registry module params to set. + Params params = 2 [(gogoproto.nullable) = false]; +} + +// MsgUpdateParamsResponse defines the response for UpdateParams. +message MsgUpdateParamsResponse {} \ No newline at end of file diff --git a/protoBindings/bindings/java/build.gradle.kts b/protoBindings/bindings/java/build.gradle.kts index dc6f6bc2c7..d2f3140a4a 100644 --- a/protoBindings/bindings/java/build.gradle.kts +++ b/protoBindings/bindings/java/build.gradle.kts @@ -36,7 +36,7 @@ dependencies { tasks.jar { archiveBaseName.set("proto-${project.name}") - exclude("**/google/**") +// exclude("**/google/**") } tasks.withType { enabled = true } @@ -67,8 +67,8 @@ sourceSets.main { proto.srcDirs(protoDirs) // Exclude Google well-known types from compilation - proto.exclude("**/google/**") - proto.exclude(excludes) +// proto.exclude("**/google/**") +// proto.exclude(excludes) } // For more advanced options see: https://github.com/google/protobuf-gradle-plugin diff --git a/protoBindings/bindings/kotlin/build.gradle.kts b/protoBindings/bindings/kotlin/build.gradle.kts index 4bc443a94c..7f863abf63 100644 --- a/protoBindings/bindings/kotlin/build.gradle.kts +++ b/protoBindings/bindings/kotlin/build.gradle.kts @@ -64,7 +64,7 @@ spotless { tasks.jar { archiveBaseName.set("proto-${project.name}") - exclude("**/google/**") +// exclude("**/google/**") } tasks.withType { enabled = true } @@ -104,8 +104,8 @@ sourceSets.main { proto.srcDirs(protoDirs) // Exclude Google well-known types from compilation - proto.exclude("**/google/**") - proto.exclude(excludes) +// proto.exclude("**/google/**") +// proto.exclude(excludes) } // For more advanced options see: https://github.com/google/protobuf-gradle-plugin diff --git a/x/ledger/keeper/authorization_test.go b/x/ledger/keeper/authorization_test.go index 7bcab72270..4cdac6a99e 100644 --- a/x/ledger/keeper/authorization_test.go +++ b/x/ledger/keeper/authorization_test.go @@ -23,7 +23,7 @@ func (s *TestSuite) TestRequireAuthorization_NoRegistry_NonOwner() { func (s *TestSuite) TestRequireAuthorization_WithServicer() { rk := ®istrytypes.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} roles := []registrytypes.RolesEntry{{Role: registrytypes.RegistryRole_REGISTRY_ROLE_SERVICER, Addresses: []string{s.addr2.String()}}} - s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, rk, roles)) + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, rk, roles, "")) // Servicer allowed err := s.keeper.RequireAuthorization(s.ctx, s.addr2.String(), rk) @@ -38,7 +38,7 @@ func (s *TestSuite) TestRequireAuthorization_WithServicer() { func (s *TestSuite) TestRequireAuthorization_EmptyServicerAddresses() { rk := ®istrytypes.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} roles := []registrytypes.RolesEntry{{Role: registrytypes.RegistryRole_REGISTRY_ROLE_SERVICER, Addresses: []string{}}} - s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, rk, roles)) + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, rk, roles, "")) // Owner allowed err := s.keeper.RequireAuthorization(s.ctx, s.addr1.String(), rk) diff --git a/x/ledger/keeper/msg_server_test.go b/x/ledger/keeper/msg_server_test.go index 183fb7e1fe..d3efad140d 100644 --- a/x/ledger/keeper/msg_server_test.go +++ b/x/ledger/keeper/msg_server_test.go @@ -490,7 +490,7 @@ func (s *MsgServerTestSuite) TestCreate() { // Create a registry if there are roles to grant if len(tc.registryEntries) > 0 { - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, ®istryKey, tc.registryEntries) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, ®istryKey, tc.registryEntries, "") s.Require().NoError(err, "CreateRegistry error") } } diff --git a/x/registry/client/cli/query.go b/x/registry/client/cli/query.go index 08d05d0a49..4e0f59d7af 100644 --- a/x/registry/client/cli/query.go +++ b/x/registry/client/cli/query.go @@ -2,6 +2,7 @@ package cli import ( "context" + "fmt" "github.com/spf13/cobra" @@ -25,6 +26,12 @@ func CmdQuery() *cobra.Command { GetCmdQueryRegistry(), GetCmdQueryRegistries(), GetCmdQueryHasRole(), + GetCmdQueryPendingRoleChange(), + GetCmdQueryPendingRoleChanges(), + GetCmdQueryRegistryClass(), + GetCmdQueryRegistryClasses(), + GetCmdQueryParams(), + GetCmdQueryValidateRoleChange(), ) return cmd @@ -141,3 +148,220 @@ func GetCmdQueryHasRole() *cobra.Command { flags.AddQueryFlagsToCmd(cmd) return cmd } + +// GetCmdQueryPendingRoleChange returns the command for querying a single pending role change by id +func GetCmdQueryPendingRoleChange() *cobra.Command { + cmd := &cobra.Command{ + Use: "pending-role-change ", + Short: "Query a pending role change by its 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) + res, err := queryClient.PendingRoleChange(context.Background(), &types.QueryPendingRoleChangeRequest{ + Id: args[0], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryPendingRoleChanges returns the command for querying pending role changes +func GetCmdQueryPendingRoleChanges() *cobra.Command { + cmd := &cobra.Command{ + Use: "pending-role-changes [asset_class_id] [nft_id]", + Short: "Query pending role changes, optionally filtered by registry key", + Args: func(_ *cobra.Command, args []string) error { + if len(args) != 0 && len(args) != 2 { + return fmt.Errorf("accepts either 0 args (all pending changes) or 2 args (asset_class_id and nft_id), received %d", len(args)) + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + var key *types.RegistryKey + if len(args) == 2 { + key = &types.RegistryKey{ + AssetClassId: args[0], + NftId: args[1], + } + } + + pageReq, err := client.ReadPageRequestWithPageKeyDecoded(cmd.Flags()) + if err != nil { + return err + } + + res, err := queryClient.PendingRoleChanges(context.Background(), &types.QueryPendingRoleChangesRequest{ + Key: key, + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "pending-role-changes") + return cmd +} + +// GetCmdQueryRegistryClass returns the command for querying a single registry class by id +func GetCmdQueryRegistryClass() *cobra.Command { + cmd := &cobra.Command{ + Use: "registry-class ", + Short: "Query a registry class (including its authorization policy) by 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) + res, err := queryClient.RegistryClass(context.Background(), &types.QueryRegistryClassRequest{ + RegistryClassId: args[0], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryRegistryClasses returns the command for querying all registry classes +func GetCmdQueryRegistryClasses() *cobra.Command { + cmd := &cobra.Command{ + Use: "registry-classes", + Short: "Query all registry classes", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequestWithPageKeyDecoded(cmd.Flags()) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.RegistryClasses(context.Background(), &types.QueryRegistryClassesRequest{ + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "registry-classes") + return cmd +} + +// GetCmdQueryParams returns the command for querying the registry module params. +func GetCmdQueryParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "params", + Short: "Query the registry module parameters", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryValidateRoleChange returns the command for the ValidateRoleChange dry-run query. +func GetCmdQueryValidateRoleChange() *cobra.Command { + cmd := &cobra.Command{ + Use: "validate-role-change ", + Short: "Dry-run a role-change batch against a set of approvers", + Long: `Check whether a set of approvers would satisfy every affected role's policy, without +writing any state. role_updates_json is a JSON array of RoleUpdate, e.g.: + + '[{"role":"REGISTRY_ROLE_CONTROLLER","addresses":["pb1newcontroller..."]}]' + +Pass one or more --approver flags with the candidate approver addresses.`, + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + approvers, err := cmd.Flags().GetStringArray("approver") + if err != nil { + return err + } + + // Parse via the proto-JSON codec so enum fields (e.g. role) accept their string names + // like "REGISTRY_ROLE_CONTROLLER" rather than only numeric values. The role_updates_json + // argument is the array; wrap it in the request message to decode it. + req := &types.QueryValidateRoleChangeRequest{} + wrapped := fmt.Sprintf(`{"role_updates": %s}`, args[2]) + if err := clientCtx.Codec.UnmarshalJSON([]byte(wrapped), req); err != nil { + return fmt.Errorf("failed to parse role_updates_json: %w", err) + } + req.Key = &types.RegistryKey{ + AssetClassId: args[0], + NftId: args[1], + } + req.Approvers = approvers + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.ValidateRoleChange(context.Background(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + cmd.Flags().StringArray("approver", nil, "a candidate approver address (repeatable)") + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/x/registry/client/cli/tx.go b/x/registry/client/cli/tx.go index dd522d0189..4eb485bf41 100644 --- a/x/registry/client/cli/tx.go +++ b/x/registry/client/cli/tx.go @@ -4,13 +4,16 @@ import ( "encoding/json" "fmt" "os" + "strings" "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" + govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + "github.com/provenance-io/provenance/internal/provcli" "github.com/provenance-io/provenance/x/registry/types" ) @@ -30,6 +33,11 @@ func CmdTx() *cobra.Command { CmdRevokeRole(), CmdUnregisterNFT(), CmdRegistryBulkUpdate(), + CmdProposeRoleChange(), + CmdApproveRoleChange(), + CmdCreateRegistryClass(), + CmdUpdateRegistryClassRoleAuthorization(), + CmdUpdateParams(), ) return cmd @@ -221,3 +229,243 @@ func CmdRegistryBulkUpdate() *cobra.Command { flags.AddTxFlagsToCmd(cmd) return cmd } + +// CmdProposeRoleChange returns the command to propose a multi-party role change +func CmdProposeRoleChange() *cobra.Command { + cmd := &cobra.Command{ + Use: "propose-role-change [role=address[,address...]...]", + Short: "Propose a desired-state role change that accumulates approvals until every affected role's policy is satisfied", + Long: `Propose a batch of desired-state role updates that accumulates single-signer approvals until +every affected role's authorization policy is satisfied, then applies atomically. + +Each role update is "role=address[,address...]". An empty address list clears the role. + +Example: + propose-role-change myclass nft1 controller=cosmos1new secured_party_for_enote=`, + Args: cobra.MinimumNArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + roleUpdates, err := parseRoleUpdates(args[2:]) + if err != nil { + return err + } + + msg := types.MsgProposeRoleChange{ + Signer: clientCtx.GetFromAddress().String(), + Key: &types.RegistryKey{ + AssetClassId: args[0], + NftId: args[1], + }, + RoleUpdates: roleUpdates, + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +// CmdApproveRoleChange returns the command to approve a pending role change +func CmdApproveRoleChange() *cobra.Command { + cmd := &cobra.Command{ + Use: "approve-role-change ", + Short: "Approve a pending role change by its id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := types.MsgApproveRoleChange{ + Signer: clientCtx.GetFromAddress().String(), + ChangeId: args[0], + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +// CmdCreateRegistryClass returns the command to create a registry class. +// The class definition (including role_authorizations) is read from a JSON file in proto-JSON +// format so that oneof fields in the authorization policy are decoded correctly. +func CmdCreateRegistryClass() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-registry-class ", + Short: "Create a registry class from a JSON file", + Long: `Create a registry class defining asset class-level authorization rules. + +The file is a proto-JSON RegistryClass, e.g.: +{ + "registry_class_id": "loan-registry-v1", + "asset_class_id": "loan.asset", + "maintainer": "pb1...", + "role_authorizations": [ { "role": "REGISTRY_ROLE_CONTROLLER", "authorizations": [ ... ] } ] +} + +If "maintainer" is omitted it defaults to the --from signer. The signer must equal the maintainer.`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + jsonData, err := os.ReadFile(args[0]) + if err != nil { + return fmt.Errorf("failed to read file: %w", err) + } + + var class types.RegistryClass + if err := clientCtx.Codec.UnmarshalJSON(jsonData, &class); err != nil { + return fmt.Errorf("failed to unmarshal registry class JSON: %w", err) + } + + signer := clientCtx.GetFromAddress().String() + maintainer := class.Maintainer + if maintainer == "" { + maintainer = signer + } + + msg := types.MsgCreateRegistryClass{ + Signer: signer, + RegistryClassId: class.RegistryClassId, + AssetClassId: class.AssetClassId, + Maintainer: maintainer, + RoleAuthorizations: class.RoleAuthorizations, + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +// CmdUpdateRegistryClassRoleAuthorization returns the command to replace a registry class's +// authorization rules. The new rules are read from a proto-JSON RegistryClass file (only its +// role_authorizations are used). +func CmdUpdateRegistryClassRoleAuthorization() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-registry-class ", + Short: "Replace a registry class's authorization rules from a JSON file", + Long: `Replace the authorization rules for an existing registry class. Only the current +maintainer may update the rules. The file is a proto-JSON RegistryClass; only its +role_authorizations field is used.`, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + jsonData, err := os.ReadFile(args[1]) + if err != nil { + return fmt.Errorf("failed to read file: %w", err) + } + + var class types.RegistryClass + if err := clientCtx.Codec.UnmarshalJSON(jsonData, &class); err != nil { + return fmt.Errorf("failed to unmarshal registry class JSON: %w", err) + } + + msg := types.MsgUpdateRegistryClassRoleAuthorization{ + Signer: clientCtx.GetFromAddress().String(), + RegistryClassId: args[0], + RoleAuthorizations: class.RoleAuthorizations, + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +// CmdUpdateParams returns the command to update the registry module params via a governance +// proposal. The params are read from a proto-JSON Params file and wrapped in a gov proposal, since +// MsgUpdateParams is authorized by the governance module account. +func CmdUpdateParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-params ", + Short: "Submit a governance proposal to update the registry module params from a JSON file", + Long: `Submit a governance proposal to update the registry module params from a proto-JSON Params file, e.g.: +{ + "role_authorizations": [ { "role": "REGISTRY_ROLE_CONTROLLER", "authorizations": [ ... ] } ] +} + +The message is wrapped in a governance proposal and must be passed by governance. The authority +defaults to the governance module account address; use --authority to override.`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + jsonData, err := os.ReadFile(args[0]) + if err != nil { + return fmt.Errorf("failed to read file: %w", err) + } + + var params types.Params + if err := clientCtx.Codec.UnmarshalJSON(jsonData, ¶ms); err != nil { + return fmt.Errorf("failed to unmarshal params JSON: %w", err) + } + + flagSet := cmd.Flags() + msg := types.MsgUpdateParams{ + Authority: provcli.GetAuthority(flagSet), + Params: params, + } + + return provcli.GenerateOrBroadcastTxCLIAsGovProp(clientCtx, flagSet, &msg) + }, + } + + govcli.AddGovPropFlagsToCmd(cmd) + provcli.AddAuthorityFlagToCmd(cmd) + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +// An empty address list (e.g. "role=") clears the role. +func parseRoleUpdates(args []string) ([]types.RoleUpdate, error) { + updates := make([]types.RoleUpdate, 0, len(args)) + for _, arg := range args { + name, addrCSV, ok := strings.Cut(arg, "=") + if !ok { + return nil, fmt.Errorf("invalid role update %q: expected format \"role=address[,address...]\"", arg) + } + + role, err := types.ParseRegistryRole(name) + if err != nil { + return nil, err + } + + var addresses []string + if trimmed := strings.TrimSpace(addrCSV); trimmed != "" { + for _, addr := range strings.Split(trimmed, ",") { + addr = strings.TrimSpace(addr) + if addr != "" { + addresses = append(addresses, addr) + } + } + } + + updates = append(updates, types.RoleUpdate{Role: role, Addresses: addresses}) + } + return updates, nil +} diff --git a/x/registry/keeper/authorization.go b/x/registry/keeper/authorization.go new file mode 100644 index 0000000000..a2b7e3ca25 --- /dev/null +++ b/x/registry/keeper/authorization.go @@ -0,0 +1,407 @@ +package keeper + +import ( + "context" + "fmt" + "strings" + + "github.com/provenance-io/provenance/x/registry/types" +) + +// resolveRegistryRoleAddresses returns the addresses for a registry role under the given +// assignment. CURRENT* variants resolve the addresses currently held for the role; NEW* variants +// resolve the incoming new addresses. +// +// The singular ASSIGNMENT_CURRENT and ASSIGNMENT_NEW variants are documented to resolve exactly +// one address and return an error if more than one would resolve. +func (k Keeper) resolveRegistryRoleAddresses(entry *types.RegistryEntry, role types.RegistryRole, assignment types.Assignment, newAddrs []string) ([]string, bool, error) { + switch assignment { + case types.Assignment_ASSIGNMENT_CURRENT, + types.Assignment_ASSIGNMENT_CURRENT_ALL, + types.Assignment_ASSIGNMENT_CURRENT_ANY: + var current []string + for _, re := range entry.Roles { + if re.Role == role { + current = re.Addresses + break + } + } + if assignment == types.Assignment_ASSIGNMENT_CURRENT && len(current) > 1 { + return nil, false, types.NewErrCodeUnauthorized( + fmt.Sprintf("ASSIGNMENT_CURRENT for role %s resolved to %d addresses, expected exactly one", role.ShortString(), len(current)), + ) + } + return current, len(current) > 0, nil + case types.Assignment_ASSIGNMENT_NEW, + types.Assignment_ASSIGNMENT_NEW_ALL, + types.Assignment_ASSIGNMENT_NEW_ANY: + if assignment == types.Assignment_ASSIGNMENT_NEW && len(newAddrs) > 1 { + return nil, false, types.NewErrCodeUnauthorized( + fmt.Sprintf("ASSIGNMENT_NEW for role %s resolved to %d addresses, expected exactly one", role.ShortString(), len(newAddrs)), + ) + } + return newAddrs, len(newAddrs) > 0, nil + default: + // Fail closed: an unspecified/unknown assignment is a policy misconfiguration and must not + // silently skip a required signature check. + return nil, false, types.NewErrCodeUnauthorized( + fmt.Sprintf("unsupported assignment %s for role %s", assignment.String(), role.ShortString()), + ) + } +} + +// resolveNFTRoleAddresses returns the address(es) for an NFT-module role (e.g. the NFT owner). +// NftRole is read-only from the registry's perspective and may only be used with the +// ASSIGNMENT_CURRENT* variants; any other assignment is a policy misconfiguration and returns an +// error. +func (k Keeper) resolveNFTRoleAddresses(ctx context.Context, entry *types.RegistryEntry, nftRole types.NftRole, assignment types.Assignment) ([]string, bool, error) { + switch assignment { + case types.Assignment_ASSIGNMENT_CURRENT, + types.Assignment_ASSIGNMENT_CURRENT_ALL, + types.Assignment_ASSIGNMENT_CURRENT_ANY: + // NftRole is only valid with the CURRENT* assignment variants. + default: + return nil, false, types.NewErrCodeUnauthorized( + fmt.Sprintf("NftRole may only be used with ASSIGNMENT_CURRENT* variants, got %s", assignment.String()), + ) + } + + switch nftRole { + case types.NftRole_NFT_ROLE_NFT_OWNER: + owner := k.GetNFTOwner(ctx, &entry.Key.AssetClassId, &entry.Key.NftId) + if len(owner) == 0 { + return nil, false, nil + } + return []string{owner.String()}, true, nil + default: + // Fail closed: an unspecified/unknown NftRole is a policy misconfiguration and must not + // silently skip a required signature check. + return nil, false, types.NewErrCodeUnauthorized( + fmt.Sprintf("unsupported NftRole %s", nftRole.String()), + ) + } +} + +// resolveRolePriorityAddresses iterates priority entries and returns addresses from the first +// non-empty role that exists, implementing the "first match wins" fallback chain. +func (k Keeper) resolveRolePriorityAddresses(ctx context.Context, entry *types.RegistryEntry, rp *types.RolePriority, assignment types.Assignment, newAddrs []string) ([]string, bool, error) { + if rp == nil { + return nil, false, nil + } + for _, e := range rp.Entries { + switch r := e.Role.(type) { + case *types.RolePriorityEntry_RegistryRole: + addrs, exists, err := k.resolveRegistryRoleAddresses(entry, r.RegistryRole, assignment, newAddrs) + if err != nil { + return nil, false, err + } + if exists { + return addrs, true, nil + } + case *types.RolePriorityEntry_NftRole: + addrs, exists, err := k.resolveNFTRoleAddresses(ctx, entry, r.NftRole, assignment) + if err != nil { + return nil, false, err + } + if exists { + return addrs, true, nil + } + } + } + return nil, false, nil +} + +// resolveRoleAssignmentAddresses dispatches to the correct resolver based on the role selector type. +func (k Keeper) resolveRoleAssignmentAddresses(ctx context.Context, entry *types.RegistryEntry, ra *types.RoleAssignment, newAddrs []string) ([]string, bool, error) { + if ra == nil { + return nil, false, nil + } + switch r := ra.RoleSelector.(type) { + case *types.RoleAssignment_RegistryRole: + return k.resolveRegistryRoleAddresses(entry, r.RegistryRole, ra.Assignment, newAddrs) + case *types.RoleAssignment_NftRole: + return k.resolveNFTRoleAddresses(ctx, entry, r.NftRole, ra.Assignment) + case *types.RoleAssignment_RolePriority: + return k.resolveRolePriorityAddresses(ctx, entry, r.RolePriority, ra.Assignment, newAddrs) + default: + // Fail closed: an unset/unknown role selector is a policy misconfiguration and must not + // silently skip a required signature check. + return nil, false, types.NewErrCodeUnauthorized("role assignment has no role selector set") + } +} + +// evaluateSignatureRequirement checks whether a single SignatureRequirement is satisfied. +// +// - REQUIRED_ALL: every resolved address from every role must be in signerSet. +// - REQUIRED_ALL_IF_SET: for each role that resolves to non-empty addresses, all must sign; +// roles that resolve to empty are skipped. +// - REQUIRED_ANY: at least one address from any role must be in signerSet. +// - REQUIRED_ANY_IF_SET: same as REQUIRED_ANY but empty roles are skipped. +func (k Keeper) evaluateSignatureRequirement(ctx context.Context, entry *types.RegistryEntry, req *types.SignatureRequirement, newAddrs []string, signerSet map[string]bool) error { + if req == nil { + return nil + } + switch req.Type { + case types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL: + for _, ra := range req.Roles { + addrs, exists, err := k.resolveRoleAssignmentAddresses(ctx, entry, ra, newAddrs) + if err != nil { + return err + } + if !exists || len(addrs) == 0 { + return types.NewErrCodeUnauthorized("required role resolved to no addresses") + } + for _, addr := range addrs { + if !signerSet[addr] { + return types.NewErrCodeUnauthorized(fmt.Sprintf("missing required signature for %q", addr)) + } + } + } + + case types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL_IF_SET: + for _, ra := range req.Roles { + addrs, exists, err := k.resolveRoleAssignmentAddresses(ctx, entry, ra, newAddrs) + if err != nil { + return err + } + if !exists || len(addrs) == 0 { + continue + } + for _, addr := range addrs { + if !signerSet[addr] { + return types.NewErrCodeUnauthorized(fmt.Sprintf("missing required signature for %q", addr)) + } + } + } + + case types.SignatureType_SIGNATURE_TYPE_REQUIRED_ANY: + found := false + for _, ra := range req.Roles { + addrs, _, err := k.resolveRoleAssignmentAddresses(ctx, entry, ra, newAddrs) + if err != nil { + return err + } + for _, addr := range addrs { + if signerSet[addr] { + found = true + break + } + } + if found { + break + } + } + if !found { + return types.NewErrCodeUnauthorized("no required signature found in any role") + } + + case types.SignatureType_SIGNATURE_TYPE_REQUIRED_ANY_IF_SET: + hasAnyRole := false + found := false + for _, ra := range req.Roles { + addrs, exists, err := k.resolveRoleAssignmentAddresses(ctx, entry, ra, newAddrs) + if err != nil { + return err + } + if !exists || len(addrs) == 0 { + continue + } + hasAnyRole = true + for _, addr := range addrs { + if signerSet[addr] { + found = true + break + } + } + if found { + break + } + } + if hasAnyRole && !found { + return types.NewErrCodeUnauthorized("no required signature found in any role") + } + + default: + // Fail closed: an unspecified/unknown signature type must not be treated as satisfied. + return types.NewErrCodeUnauthorized( + fmt.Sprintf("unsupported signature requirement type %s", req.Type.String()), + ) + } + return nil +} + +// evaluateAuthorization checks whether every SignatureRequirement in an authorization path is +// satisfied. Returns nil if all requirements pass, or an error describing the first failure. +func (k Keeper) evaluateAuthorization(ctx context.Context, entry *types.RegistryEntry, auth *types.Authorization, newAddrs []string, signerSet map[string]bool) error { + if auth == nil { + return nil + } + for i, req := range auth.Signatures { + if err := k.evaluateSignatureRequirement(ctx, entry, req, newAddrs, signerSet); err != nil { + return fmt.Errorf("signature requirement %d: %w", i, err) + } + } + return nil +} + +// ValidateRoleChangeAuthorization validates that the provided signers are authorized to update a +// role on the given entry. It tries each authorization path in the RoleAuthorization; the +// operation is approved as soon as any single path is fully satisfied. +// +// newAddrs contains the addresses being assigned to the role (used for ASSIGNMENT_NEW checks). +// For revoke operations, newAddrs should be nil or empty. +func (k Keeper) ValidateRoleChangeAuthorization(ctx context.Context, roleAuth types.RoleAuthorization, entry *types.RegistryEntry, newAddrs []string, signers []string) error { + signerSet := make(map[string]bool, len(signers)) + for _, s := range signers { + signerSet[s] = true + } + + var pathErrors []string + for _, auth := range roleAuth.Authorizations { + if err := k.evaluateAuthorization(ctx, entry, auth, newAddrs, signerSet); err == nil { + return nil + } else { + desc := auth.Description + if desc == "" { + desc = fmt.Sprintf("path %d", len(pathErrors)+1) + } + pathErrors = append(pathErrors, fmt.Sprintf("%s: %v", desc, err)) + } + } + + return types.NewErrCodeUnauthorized( + fmt.Sprintf("no valid authorization path found for %s: %s", roleAuth.Role.ShortString(), strings.Join(pathErrors, "; ")), + ) +} + +// CollectPolicyApprovers returns the set of addresses that the given role authorization policy +// could ever require to sign, resolved against the entry and the addresses being newly assigned. +// These are the only approvers whose signature can contribute to satisfying the policy; any other +// address is, by definition, a no-op approver. Resolution errors from a misconfigured path are +// ignored here (the path simply contributes no eligible addresses). +func (k Keeper) CollectPolicyApprovers(ctx context.Context, roleAuth types.RoleAuthorization, entry *types.RegistryEntry, newAddrs []string) map[string]bool { + out := make(map[string]bool) + for _, auth := range roleAuth.Authorizations { + if auth == nil { + continue + } + for _, req := range auth.Signatures { + if req == nil { + continue + } + for _, ra := range req.Roles { + addrs, _, _ := k.resolveRoleAssignmentAddresses(ctx, entry, ra, newAddrs) + for _, addr := range addrs { + out[addr] = true + } + } + } + } + return out +} + +// resolveRoleAssignmentSigner is like resolveRoleAssignmentAddresses but also returns the concrete +// role name that resolved (used to build EventRoleUpdated.signers). For a role_priority selector it +// returns the first matching priority entry's role name. +func (k Keeper) resolveRoleAssignmentSigner(ctx context.Context, entry *types.RegistryEntry, ra *types.RoleAssignment, newAddrs []string) (string, []string, bool, error) { + if ra == nil { + return "", nil, false, nil + } + switch r := ra.RoleSelector.(type) { + case *types.RoleAssignment_RegistryRole: + addrs, exists, err := k.resolveRegistryRoleAddresses(entry, r.RegistryRole, ra.Assignment, newAddrs) + return r.RegistryRole.String(), addrs, exists, err + case *types.RoleAssignment_NftRole: + addrs, exists, err := k.resolveNFTRoleAddresses(ctx, entry, r.NftRole, ra.Assignment) + return r.NftRole.String(), addrs, exists, err + case *types.RoleAssignment_RolePriority: + if r.RolePriority == nil { + return "", nil, false, nil + } + for _, e := range r.RolePriority.Entries { + switch pe := e.Role.(type) { + case *types.RolePriorityEntry_RegistryRole: + addrs, exists, err := k.resolveRegistryRoleAddresses(entry, pe.RegistryRole, ra.Assignment, newAddrs) + if err != nil { + return "", nil, false, err + } + if exists { + return pe.RegistryRole.String(), addrs, true, nil + } + case *types.RolePriorityEntry_NftRole: + addrs, exists, err := k.resolveNFTRoleAddresses(ctx, entry, pe.NftRole, ra.Assignment) + if err != nil { + return "", nil, false, err + } + if exists { + return pe.NftRole.String(), addrs, true, nil + } + } + } + return "", nil, false, nil + default: + return "", nil, false, nil + } +} + +// collectAuthorizationSigners builds the list of RoleSigner entries describing which roles and +// addresses contributed signatures to satisfy the given (already-satisfied) authorization path. +func (k Keeper) collectAuthorizationSigners(ctx context.Context, entry *types.RegistryEntry, auth *types.Authorization, newAddrs []string, signerSet map[string]bool) []types.RoleSigner { + var signers []types.RoleSigner + if auth == nil { + return signers + } + for _, req := range auth.Signatures { + if req == nil { + continue + } + switch req.Type { + case types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL, + types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL_IF_SET: + // In a satisfied path every resolved (set) role signed, so report all of them. + for _, ra := range req.Roles { + name, addrs, exists, err := k.resolveRoleAssignmentSigner(ctx, entry, ra, newAddrs) + if err != nil || !exists || len(addrs) == 0 { + continue + } + signers = append(signers, types.RoleSigner{Role: name, Assignment: ra.Assignment.String(), Addresses: addrs}) + } + case types.SignatureType_SIGNATURE_TYPE_REQUIRED_ANY, + types.SignatureType_SIGNATURE_TYPE_REQUIRED_ANY_IF_SET: + // Only the role whose address actually signed contributed; report the signing subset. + for _, ra := range req.Roles { + name, addrs, exists, err := k.resolveRoleAssignmentSigner(ctx, entry, ra, newAddrs) + if err != nil || !exists { + continue + } + var signed []string + for _, a := range addrs { + if signerSet[a] { + signed = append(signed, a) + } + } + if len(signed) > 0 { + signers = append(signers, types.RoleSigner{Role: name, Assignment: ra.Assignment.String(), Addresses: signed}) + break + } + } + } + } + return signers +} + +// CollectSatisfyingSigners finds the first authorization path satisfied by signers and returns the +// RoleSigner entries describing who authorized the change. It returns nil if no path is satisfied +// (e.g. for the legacy NFT-owner fallback, which has no policy). +func (k Keeper) CollectSatisfyingSigners(ctx context.Context, roleAuth types.RoleAuthorization, entry *types.RegistryEntry, newAddrs []string, signers []string) []types.RoleSigner { + signerSet := make(map[string]bool, len(signers)) + for _, s := range signers { + signerSet[s] = true + } + for _, auth := range roleAuth.Authorizations { + if k.evaluateAuthorization(ctx, entry, auth, newAddrs, signerSet) == nil { + return k.collectAuthorizationSigners(ctx, entry, auth, newAddrs, signerSet) + } + } + return nil +} diff --git a/x/registry/keeper/authorization_engine_test.go b/x/registry/keeper/authorization_engine_test.go new file mode 100644 index 0000000000..590c030aaf --- /dev/null +++ b/x/registry/keeper/authorization_engine_test.go @@ -0,0 +1,173 @@ +package keeper_test + +import ( + "github.com/provenance-io/provenance/x/registry/types" +) + +// These tests exercise the policy engine's fail-closed branches directly via +// ValidateRoleChangeAuthorization. A misconfigured policy (unspecified enums, singular assignments +// resolving to more than one address, selectors used in unsupported ways) must surface an error and +// must NEVER be silently treated as satisfied. + +// engineEntry builds an in-memory registry entry (owned by s.user1) seeded with the given roles. +func (s *KeeperTestSuite) engineEntry(roles []types.RolesEntry) *types.RegistryEntry { + return &types.RegistryEntry{ + Key: &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id}, + Roles: roles, + } +} + +// singleSigPolicy wraps one role selector in a REQUIRED_ALL single-path policy for the SERVICER role. +func singleSigPolicy(ra *types.RoleAssignment) types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{ + Description: "engine fail-closed path", + Signatures: []*types.SignatureRequirement{{ + Type: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL, + Roles: []*types.RoleAssignment{ra}, + }}, + }}, + } +} + +func (s *KeeperTestSuite) TestEngine_AssignmentCurrentResolvesMultiple() { + // CONTROLLER currently held by two addresses; singular ASSIGNMENT_CURRENT must reject. + entry := s.engineEntry([]types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1, s.user2}}, + }) + policy := singleSigPolicy(&types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RegistryRole{RegistryRole: types.RegistryRole_REGISTRY_ROLE_CONTROLLER}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + }) + + err := s.app.RegistryKeeper.ValidateRoleChangeAuthorization(s.ctx, policy, entry, nil, []string{s.user1, s.user2}) + s.Require().Error(err) + s.Require().Contains(err.Error(), "ASSIGNMENT_CURRENT for role CONTROLLER resolved to 2 addresses, expected exactly one") +} + +func (s *KeeperTestSuite) TestEngine_AssignmentNewResolvesMultiple() { + entry := s.engineEntry(nil) + policy := singleSigPolicy(&types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RegistryRole{RegistryRole: types.RegistryRole_REGISTRY_ROLE_SERVICER}, + Assignment: types.Assignment_ASSIGNMENT_NEW, + }) + + newAddrs := []string{s.user1, s.user2} + err := s.app.RegistryKeeper.ValidateRoleChangeAuthorization(s.ctx, policy, entry, newAddrs, newAddrs) + s.Require().Error(err) + s.Require().Contains(err.Error(), "ASSIGNMENT_NEW for role SERVICER resolved to 2 addresses, expected exactly one") +} + +func (s *KeeperTestSuite) TestEngine_UnspecifiedAssignment() { + entry := s.engineEntry([]types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }) + policy := singleSigPolicy(&types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RegistryRole{RegistryRole: types.RegistryRole_REGISTRY_ROLE_CONTROLLER}, + Assignment: types.Assignment_ASSIGNMENT_UNSPECIFIED, + }) + + err := s.app.RegistryKeeper.ValidateRoleChangeAuthorization(s.ctx, policy, entry, nil, []string{s.user1}) + s.Require().Error(err) + s.Require().Contains(err.Error(), "unsupported assignment") +} + +func (s *KeeperTestSuite) TestEngine_NftRoleWithNonCurrentAssignment() { + entry := s.engineEntry(nil) + policy := singleSigPolicy(&types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_NftRole{NftRole: types.NftRole_NFT_ROLE_NFT_OWNER}, + Assignment: types.Assignment_ASSIGNMENT_NEW, + }) + + err := s.app.RegistryKeeper.ValidateRoleChangeAuthorization(s.ctx, policy, entry, nil, []string{s.user1}) + s.Require().Error(err) + s.Require().Contains(err.Error(), "NftRole may only be used with ASSIGNMENT_CURRENT* variants") +} + +func (s *KeeperTestSuite) TestEngine_UnsupportedNftRole() { + entry := s.engineEntry(nil) + policy := singleSigPolicy(&types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_NftRole{NftRole: types.NftRole_NFT_ROLE_UNSPECIFIED}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + }) + + err := s.app.RegistryKeeper.ValidateRoleChangeAuthorization(s.ctx, policy, entry, nil, []string{s.user1}) + s.Require().Error(err) + s.Require().Contains(err.Error(), "unsupported NftRole") +} + +func (s *KeeperTestSuite) TestEngine_NoRoleSelectorSet() { + entry := s.engineEntry(nil) + policy := singleSigPolicy(&types.RoleAssignment{ + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + }) + + err := s.app.RegistryKeeper.ValidateRoleChangeAuthorization(s.ctx, policy, entry, nil, []string{s.user1}) + s.Require().Error(err) + s.Require().Contains(err.Error(), "role assignment has no role selector set") +} + +func (s *KeeperTestSuite) TestEngine_UnsupportedSignatureType() { + entry := s.engineEntry([]types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }) + policy := types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{ + Description: "bad signature type", + Signatures: []*types.SignatureRequirement{{ + Type: types.SignatureType_SIGNATURE_TYPE_UNSPECIFIED, + Roles: []*types.RoleAssignment{{ + RoleSelector: &types.RoleAssignment_RegistryRole{RegistryRole: types.RegistryRole_REGISTRY_ROLE_CONTROLLER}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + }}, + }}, + }}, + } + + err := s.app.RegistryKeeper.ValidateRoleChangeAuthorization(s.ctx, policy, entry, nil, []string{s.user1}) + s.Require().Error(err) + s.Require().Contains(err.Error(), "unsupported signature requirement type") +} + +// TestEngine_RequiredAnyIfSet_NoRolesSet confirms REQUIRED_ANY_IF_SET passes (vacuously) when none +// of its roles resolve to addresses, while REQUIRED_ANY rejects in the same situation. This is the +// empty-role distinction between the two ANY signature types. +func (s *KeeperTestSuite) TestEngine_RequiredAnyIfSet_NoRolesSet() { + // Entry has no SECURED_PARTY_FOR_ENOTE set, so the selector resolves empty. + entry := s.engineEntry(nil) + selector := &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RegistryRole{RegistryRole: types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT_ANY, + } + + s.Run("required_any_if_set passes when no role resolves", func() { + policy := types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{ + Signatures: []*types.SignatureRequirement{{ + Type: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ANY_IF_SET, + Roles: []*types.RoleAssignment{selector}, + }}, + }}, + } + err := s.app.RegistryKeeper.ValidateRoleChangeAuthorization(s.ctx, policy, entry, nil, nil) + s.Require().NoError(err) + }) + + s.Run("required_any rejects when no role resolves", func() { + policy := types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{ + Signatures: []*types.SignatureRequirement{{ + Type: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ANY, + Roles: []*types.RoleAssignment{selector}, + }}, + }}, + } + err := s.app.RegistryKeeper.ValidateRoleChangeAuthorization(s.ctx, policy, entry, nil, nil) + s.Require().Error(err) + s.Require().Contains(err.Error(), "no required signature found in any role") + }) +} diff --git a/x/registry/keeper/class.go b/x/registry/keeper/class.go new file mode 100644 index 0000000000..ca60ff039a --- /dev/null +++ b/x/registry/keeper/class.go @@ -0,0 +1,163 @@ +package keeper + +import ( + "context" + "errors" + "fmt" + + "cosmossdk.io/collections" + "github.com/cosmos/cosmos-sdk/types/query" + + "github.com/provenance-io/provenance/x/registry/types" +) + +// GetRegistryClass returns the registry class for the given id. If no class exists for the id, it +// returns nil, nil. +func (k Keeper) GetRegistryClass(ctx context.Context, registryClassID string) (*types.RegistryClass, error) { + class, err := k.RegistryClasses.Get(ctx, registryClassID) + if err != nil { + if errors.Is(err, collections.ErrNotFound) { + return nil, nil + } + return nil, err + } + return &class, nil +} + +// HasRegistryClass reports whether a registry class exists for the given id. +func (k Keeper) HasRegistryClass(ctx context.Context, registryClassID string) (bool, error) { + return k.RegistryClasses.Has(ctx, registryClassID) +} + +// validateRegistryClassForEntry verifies that an entry may reference the given registry class id. +// When the id is empty there is nothing to check. Otherwise the class must exist and its asset +// class id must match the entry's asset class id; a registry class only governs entries within its +// own asset class, so a mismatch would resolve authorization against the wrong policy tier. +func (k Keeper) validateRegistryClassForEntry(ctx context.Context, registryClassID, assetClassID string) error { + if registryClassID == "" { + return nil + } + class, err := k.GetRegistryClass(ctx, registryClassID) + if err != nil { + return err + } + if class == nil { + return types.NewErrCodeRegistryClassNotFound(registryClassID) + } + if class.AssetClassId != assetClassID { + return types.NewErrCodeRegistryClassAssetMismatch(registryClassID, class.AssetClassId, assetClassID) + } + return nil +} + +// SetRegistryClass stores a registry class in state. +func (k Keeper) SetRegistryClass(ctx context.Context, class types.RegistryClass) error { + return k.RegistryClasses.Set(ctx, class.RegistryClassId, class) +} + +// CreateRegistryClass stores a new registry class. It returns an error if a class already exists +// with the same id. +func (k Keeper) CreateRegistryClass(ctx context.Context, class types.RegistryClass) error { + if err := class.Validate(); err != nil { + return err + } + + has, err := k.RegistryClasses.Has(ctx, class.RegistryClassId) + if err != nil { + return fmt.Errorf("could not check if registry class exists: %w", err) + } + if has { + return types.NewErrCodeRegistryClassExists(class.RegistryClassId) + } + + if err = k.SetRegistryClass(ctx, class); err != nil { + return fmt.Errorf("could not set registry class: %w", err) + } + + k.EmitEvent(ctx, types.NewEventRegistryClassCreated(&class)) + return nil +} + +// UpdateRegistryClassRoleAuthorization replaces the authorization rules for an existing registry +// class. Only the current maintainer (the provided signer) may update the rules. The maintainer +// and asset class id are immutable. +func (k Keeper) UpdateRegistryClassRoleAuthorization(ctx context.Context, signer, registryClassID string, roleAuths []types.RoleAuthorization) error { + class, err := k.GetRegistryClass(ctx, registryClassID) + if err != nil { + return fmt.Errorf("could not get registry class: %w", err) + } + if class == nil { + return types.NewErrCodeRegistryClassNotFound(registryClassID) + } + + if signer != class.Maintainer { + return types.NewErrCodeUnauthorized( + fmt.Sprintf("signer %q is not the maintainer of registry class %q", signer, registryClassID), + ) + } + + class.RoleAuthorizations = roleAuths + if err = class.Validate(); err != nil { + return err + } + if err = k.SetRegistryClass(ctx, *class); err != nil { + return fmt.Errorf("could not set registry class: %w", err) + } + + k.EmitEvent(ctx, types.NewEventRegistryClassUpdated(class)) + return nil +} + +// GetRegistryClasses returns the registry classes paginated. +func (k Keeper) GetRegistryClasses(ctx context.Context, pagination *query.PageRequest) ([]types.RegistryClass, *query.PageResponse, error) { + ptrs, pageRes, err := query.CollectionPaginate(ctx, k.RegistryClasses, pagination, func(_ string, class types.RegistryClass) (*types.RegistryClass, error) { + return &class, nil + }) + if err != nil { + return nil, nil, err + } + + classes := make([]types.RegistryClass, len(ptrs)) + for i, p := range ptrs { + classes[i] = *p + } + return classes, pageRes, nil +} + +// roleAuthorizationsForEntry resolves the effective role authorization policies that govern role +// updates for the given registry entry, implementing the two-tier resolution: +// +// 1. Registry class level (highest priority): if the entry references a registry class that +// exists, use the authorization rules defined by that class. +// 2. Module params default (fallback): otherwise use the module's default policies (governance- +// managed via MsgUpdateParams). Roles not covered by the returned map fall back to legacy +// NFT-owner authorization at the call site. +// +// It returns a deterministic error (rather than panicking) when a referenced class cannot be +// resolved: a store read error, a class that is absent from state, or a class whose asset class +// does not match the entry. These conditions indicate inconsistent state and must fail closed, +// never silently downgrading to a weaker authorization tier, but they must also not halt block +// processing. +func (k Keeper) roleAuthorizationsForEntry(ctx context.Context, entry *types.RegistryEntry) (map[types.RegistryRole]types.RoleAuthorization, error) { + if entry != nil && entry.RegistryClassId != "" { + class, err := k.GetRegistryClass(ctx, entry.RegistryClassId) + if err != nil { + // A store/read error must not silently downgrade to a weaker fallback policy. + return nil, fmt.Errorf("could not resolve registry class %q for authorization: %w", entry.RegistryClassId, err) + } + if class == nil { + // The entry references a registry class that is not present in state. Falling back to + // params/legacy here would be an implicit fail-open authorization downgrade, so fail + // closed instead. + return nil, types.NewErrCodeRegistryClassNotFound(entry.RegistryClassId) + } + // Defense in depth: enforcement at write time (register, bulk update, genesis) keeps the + // referenced class scoped to the entry's asset class. If a mismatched class is ever found in + // state, fail closed rather than resolve authorization against the wrong policy tier. + if entry.Key != nil && class.AssetClassId != entry.Key.AssetClassId { + return nil, types.NewErrCodeRegistryClassAssetMismatch(entry.RegistryClassId, class.AssetClassId, entry.Key.AssetClassId) + } + return types.RoleAuthorizationMapFrom(class.RoleAuthorizations), nil + } + return k.GetParams(ctx).RoleAuthorizationMap(), nil +} diff --git a/x/registry/keeper/genesis.go b/x/registry/keeper/genesis.go index f194bd02d8..53a60133fd 100644 --- a/x/registry/keeper/genesis.go +++ b/x/registry/keeper/genesis.go @@ -14,6 +14,19 @@ func (k Keeper) InitGenesis(ctx context.Context, state *types.GenesisState) { panic(err) // Genesis should not fail } } + for _, change := range state.PendingRoleChanges { + if err := k.PendingRoleChanges.Set(ctx, change.Id, change); err != nil { + panic(err) // Genesis should not fail + } + } + for _, class := range state.RegistryClasses { + if err := k.RegistryClasses.Set(ctx, class.RegistryClassId, class); err != nil { + panic(err) // Genesis should not fail + } + } + if err := k.Params.Set(ctx, state.Params); err != nil { + panic(err) // Genesis should not fail + } } func (k Keeper) ExportGenesis(ctx context.Context) *types.GenesisState { @@ -27,5 +40,23 @@ func (k Keeper) ExportGenesis(ctx context.Context) *types.GenesisState { panic(err) } + err = k.PendingRoleChanges.Walk(ctx, nil, func(_ string, value types.PendingRoleChange) (stop bool, err error) { + genesis.PendingRoleChanges = append(genesis.PendingRoleChanges, value) + return false, nil + }) + if err != nil { + panic(err) + } + + err = k.RegistryClasses.Walk(ctx, nil, func(_ string, value types.RegistryClass) (stop bool, err error) { + genesis.RegistryClasses = append(genesis.RegistryClasses, value) + return false, nil + }) + if err != nil { + panic(err) + } + + genesis.Params = k.GetParams(ctx) + return genesis } diff --git a/x/registry/keeper/genesis_test.go b/x/registry/keeper/genesis_test.go index 6a90410f97..4cd900042e 100644 --- a/x/registry/keeper/genesis_test.go +++ b/x/registry/keeper/genesis_test.go @@ -224,7 +224,7 @@ func (s *KeeperTestSuite) TestExportGenesis() { Addresses: []string{s.user1}, }, } - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles, "") s.Require().NoError(err) }, expEntries: []types.RegistryEntry{ @@ -276,7 +276,7 @@ func (s *KeeperTestSuite) TestExportGenesis() { } for _, e := range entries { - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, e.key, e.roles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, e.key, e.roles, "") s.Require().NoError(err) } }, @@ -377,9 +377,9 @@ func (s *KeeperTestSuite) TestGenesisRoundTrip() { } // Create registries - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key1, roles1) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key1, roles1, "") s.Require().NoError(err) - err = s.app.RegistryKeeper.CreateRegistry(s.ctx, key2, roles2) + err = s.app.RegistryKeeper.CreateRegistry(s.ctx, key2, roles2, "") s.Require().NoError(err) // Export genesis diff --git a/x/registry/keeper/keeper.go b/x/registry/keeper/keeper.go index facd719377..8b4cf9b663 100644 --- a/x/registry/keeper/keeper.go +++ b/x/registry/keeper/keeper.go @@ -14,14 +14,22 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/gogoproto/proto" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/provenance-io/provenance/x/registry/types" ) // Keeper defines the registry keeper. type Keeper struct { - cdc codec.BinaryCodec - schema collections.Schema - Registry collections.Map[collections.Pair[string, string], types.RegistryEntry] + cdc codec.BinaryCodec + schema collections.Schema + Registry collections.Map[collections.Pair[string, string], types.RegistryEntry] + PendingRoleChanges collections.Map[string, types.PendingRoleChange] + RegistryClasses collections.Map[string, types.RegistryClass] + Params collections.Item[types.Params] + + authority string NFTKeeper NFTKeeper MetadataKeeper MetadataKeeper @@ -42,6 +50,31 @@ func NewKeeper(cdc codec.BinaryCodec, storeService store.KVStoreService, nftKeep codec.CollValue[types.RegistryEntry](cdc), ), + PendingRoleChanges: collections.NewMap( + sb, + collections.NewPrefix(pendingRoleChangePrefix), + "pending_role_changes", + collections.StringKey, + codec.CollValue[types.PendingRoleChange](cdc), + ), + + RegistryClasses: collections.NewMap( + sb, + collections.NewPrefix(registryClassPrefix), + "registry_classes", + collections.StringKey, + codec.CollValue[types.RegistryClass](cdc), + ), + + Params: collections.NewItem( + sb, + collections.NewPrefix(paramsPrefix), + "params", + codec.CollValue[types.Params](cdc), + ), + + authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + NFTKeeper: nftKeeper, MetadataKeeper: metaDataKeeper, } @@ -85,12 +118,24 @@ func (k Keeper) CreateDefaultRegistry(ctx context.Context, ownerAddrStr string, Addresses: []string{ownerAddrStr}, } - return k.CreateRegistry(ctx, key, roles) + return k.CreateRegistry(ctx, key, roles, "") } // CreateRegistry stores a new registry entry in state. // Returns an error if the registry already exists, or if there's a problem. -func (k Keeper) CreateRegistry(ctx context.Context, key *types.RegistryKey, roles []types.RolesEntry) error { +func (k Keeper) CreateRegistry(ctx context.Context, key *types.RegistryKey, roles []types.RolesEntry, registryClassID string) error { + if key == nil { + return fmt.Errorf("registry key must not be nil") + } + + // Defense in depth: enforce the registry class invariant at the keeper layer so invalid state + // cannot be introduced via direct keeper calls (other modules/tests) that bypass the msg and + // genesis validation paths. When set, the class must exist and be scoped to this entry's asset + // class; otherwise authorization would later resolve against the wrong policy tier. + if err := k.validateRegistryClassForEntry(ctx, registryClassID, key.AssetClassId); err != nil { + return err + } + // Already exists check has, err := k.Registry.Has(ctx, key.CollKey()) if err != nil { @@ -101,8 +146,9 @@ func (k Keeper) CreateRegistry(ctx context.Context, key *types.RegistryKey, role } err = k.Registry.Set(ctx, key.CollKey(), types.RegistryEntry{ - Key: key, - Roles: roles, + Key: key, + Roles: roles, + RegistryClassId: registryClassID, }) if err != nil { return fmt.Errorf("could not set registry entry: %w", err) @@ -129,6 +175,17 @@ func (k Keeper) DeleteRegistry(ctx context.Context, key *types.RegistryKey) erro return fmt.Errorf("error removing registry: %w", err) } + // Remove any pending role changes so stale approvals cannot be replayed if the NFT is re-registered. + pending, _, err := k.GetPendingRoleChanges(ctx, nil, key) + if err != nil { + return fmt.Errorf("error fetching pending role changes for cleanup: %w", err) + } + for _, pc := range pending { + if err := k.RemovePendingRoleChange(ctx, pc.Id); err != nil { + return fmt.Errorf("error removing stale pending role change %s: %w", pc.Id, err) + } + } + k.EmitEvent(ctx, types.NewEventNFTUnregistered(key)) for _, entry := range reg.Roles { k.EmitEvent(ctx, types.NewEventRoleRevoked(key, entry.Role, entry.Addresses)) @@ -235,6 +292,50 @@ func (k Keeper) RevokeRole(ctx context.Context, key *types.RegistryKey, role typ return nil } +// roleChangeSigners resolves the RoleSigner entries describing who authorized a role change for the +// given role. For a policy-governed role it returns the satisfying authorization path's signers; for +// a non-policy role it returns the NFT owner among the approvers (the legacy fallback). before is the +// pre-mutation entry, newAddrs the addresses being assigned to the role, and approvers the signers. +func (k Keeper) roleChangeSigners(ctx context.Context, before *types.RegistryEntry, role types.RegistryRole, newAddrs, approvers []string) ([]types.RoleSigner, error) { + roleAuths, err := k.roleAuthorizationsForEntry(ctx, before) + if err != nil { + return nil, err + } + if roleAuth, ok := roleAuths[role]; ok { + return k.CollectSatisfyingSigners(ctx, roleAuth, before, newAddrs, approvers), nil + } + for _, a := range approvers { + if k.ValidateNFTOwner(ctx, &before.Key.AssetClassId, &before.Key.NftId, a) == nil { + return []types.RoleSigner{types.NewNFTOwnerSigner(a)}, nil + } + } + return nil, nil +} + +// emitRoleUpdated emits the comprehensive EventRoleUpdated for a single role, reading the +// post-mutation addresses from state. before is the pre-mutation entry (source of previous +// addresses and registry class id), and signers is the authorizing signer set. It returns a +// deterministic error (rather than panicking) if the post-mutation read-back fails, so an +// inconsistent store cannot halt block processing. +func (k Keeper) emitRoleUpdated(ctx context.Context, before *types.RegistryEntry, role types.RegistryRole, signers []types.RoleSigner) error { + previous := before.GetRoleAddrs(role) + var current []string + after, err := k.GetRegistry(ctx, before.Key) + if err != nil { + // The mutation has already been committed; a read-back error means the store is + // inconsistent. Surface the error rather than emit a misleading audit event with empty + // addresses; returning it rolls back the transaction deterministically. + return fmt.Errorf("could not read back registry %q for EventRoleUpdated: %w", before.Key.String(), err) + } + // after may legitimately be nil if the role change removed the entry's last role and the entry + // was cleaned up; in that case current is correctly empty. + if after != nil { + current = after.GetRoleAddrs(role) + } + k.EmitEvent(ctx, types.NewEventRoleUpdated(before.Key, before.RegistryClassId, role, previous, current, signers)) + return nil +} + func (k Keeper) HasRole(ctx context.Context, key *types.RegistryKey, role types.RegistryRole, address string) (bool, error) { registryEntry, err := k.Registry.Get(ctx, key.CollKey()) if err != nil { @@ -286,6 +387,65 @@ func (k Keeper) SetRegistry(ctx context.Context, entry types.RegistryEntry) erro return k.Registry.Set(ctx, entry.Key.CollKey(), entry) } +// SetRoles atomically sets the desired state for one or more roles on a registry entry. +// Each RoleUpdate specifies a role and the complete desired set of addresses; an empty +// address list clears the role entirely. +func (k Keeper) SetRoles(ctx context.Context, key *types.RegistryKey, roleUpdates []types.RoleUpdate) error { + entry, err := k.Registry.Get(ctx, key.CollKey()) + if err != nil { + if errors.Is(err, collections.ErrNotFound) { + return types.NewErrCodeRegistryNotFound(key.String()) + } + return fmt.Errorf("failed to get registry entry: %w", err) + } + + // Snapshot the original entry to compute diff events. The loop below mutates entry.Roles + // (and individual Addresses slices) in place, so a shallow copy would corrupt the snapshot + // and produce incorrect diffs. Deep-copy the Roles slice and each Addresses slice. + origCopy := entry + origCopy.Roles = make([]types.RolesEntry, len(entry.Roles)) + for i, re := range entry.Roles { + origCopy.Roles[i] = types.RolesEntry{Role: re.Role, Addresses: slices.Clone(re.Addresses)} + } + + for _, update := range roleUpdates { + roleI := -1 + for i, re := range entry.Roles { + if re.Role == update.Role { + roleI = i + break + } + } + + if len(update.Addresses) == 0 { + // Clear the role if present. + if roleI >= 0 { + entry.Roles = append(entry.Roles[:roleI], entry.Roles[roleI+1:]...) + } + } else { + // Set the complete desired address list for the role. + if roleI >= 0 { + entry.Roles[roleI].Addresses = update.Addresses + } else { + entry.Roles = append(entry.Roles, types.RolesEntry{Role: update.Role, Addresses: update.Addresses}) + } + } + } + + if err = k.Registry.Set(ctx, key.CollKey(), entry); err != nil { + return fmt.Errorf("failed to set registry entry: %w", err) + } + + grantEvents, revokeEvents := types.GetChangeEvents(&origCopy, &entry) + for _, tev := range grantEvents { + k.EmitEvent(ctx, tev) + } + for _, tev := range revokeEvents { + k.EmitEvent(ctx, tev) + } + return nil +} + // GetRegistries returns the registries paginated func (k Keeper) GetRegistries(ctx context.Context, pagination *query.PageRequest, assetClassID string) ([]types.RegistryEntry, *query.PageResponse, error) { var opts []func(opt *query.CollectionsPaginateOptions[collections.Pair[string, string]]) diff --git a/x/registry/keeper/keeper_test.go b/x/registry/keeper/keeper_test.go index d27f55384c..10e1b060ed 100644 --- a/x/registry/keeper/keeper_test.go +++ b/x/registry/keeper/keeper_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/google/uuid" "github.com/stretchr/testify/suite" "cosmossdk.io/x/nft" @@ -17,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" "github.com/provenance-io/provenance/app" + metadatatypes "github.com/provenance-io/provenance/x/metadata/types" "github.com/provenance-io/provenance/testutil/assertions" "github.com/provenance-io/provenance/x/registry/keeper" "github.com/provenance-io/provenance/x/registry/types" @@ -116,7 +118,7 @@ func (s *KeeperTestSuite) TestCreateRegistry() { }, } - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles, "") s.Require().NoError(err) // Verify registry was created @@ -128,10 +130,59 @@ func (s *KeeperTestSuite) TestCreateRegistry() { // Test duplicate creation not allowed. expDupErr := "registry already exists for key: \"" + key.String() + "\": registry already exists" - err = s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles) + err = s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles, "") s.Require().EqualError(err, expDupErr) } +// TestCreateRegistry_RejectsInvalidClassReference verifies the keeper-layer invariant that an entry +// may only be created with a registry class id that exists and is scoped to the entry's asset class. +// This guards against invalid state introduced via direct keeper calls that bypass msg/genesis. +func (s *KeeperTestSuite) TestCreateRegistry_RejectsInvalidClassReference() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: "create-registry-bad-class-nft", + } + + // A nil key must be rejected rather than panic. + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, nil, nil, "") + s.Require().EqualError(err, "registry key must not be nil") + + // Referencing a class that does not exist must fail closed. + err = s.app.RegistryKeeper.CreateRegistry(s.ctx, key, nil, "missing-class") + s.Require().ErrorIs(err, types.NewErrCodeRegistryClassNotFound("missing-class")) + + // The entry must not have been written. + entry, err := s.app.RegistryKeeper.GetRegistry(s.ctx, key) + s.Require().NoError(err) + s.Require().Nil(entry) +} + +// TestRoleAuthorizationsForEntry_FailsClosedOnMissingClass verifies that resolving authorization for +// an entry whose registry class id is absent from state fails closed: the role-change message +// returns a deterministic error (rather than panicking or silently downgrading to the params/legacy +// authorization tier), so an inconsistent store cannot halt block processing. +func (s *KeeperTestSuite) TestRoleAuthorizationsForEntry_FailsClosedOnMissingClass() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: "fail-closed-missing-class-nft", + } + // Seed the entry directly to bypass CreateRegistry's validation, simulating corrupt state or a + // class that was removed after the entry referenced it. + s.Require().NoError(s.app.RegistryKeeper.SetRegistry(s.ctx, types.RegistryEntry{ + Key: key, + RegistryClassId: "missing-class", + })) + + msgServer := keeper.NewMsgServer(s.app.RegistryKeeper) + _, err := msgServer.GrantRole(s.ctx, &types.MsgGrantRole{ + Signer: s.user1, + Key: key, + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{s.user1}, + }) + s.Require().ErrorIs(err, types.NewErrCodeRegistryClassNotFound("missing-class")) +} + func (s *KeeperTestSuite) TestGrantRole() { // Create a base registry for testing baseKey := &types.RegistryKey{ @@ -144,7 +195,7 @@ func (s *KeeperTestSuite) TestGrantRole() { Addresses: []string{s.user1Addr.String()}, }, } - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, baseKey, baseRoles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, baseKey, baseRoles, "") s.Require().NoError(err) tests := []struct { @@ -239,7 +290,7 @@ func (s *KeeperTestSuite) TestRevokeRole() { Addresses: []string{s.user1Addr.String(), s.user2Addr.String()}, }, } - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, baseKey, baseRoles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, baseKey, baseRoles, "") s.Require().NoError(err) tests := []struct { @@ -322,7 +373,7 @@ func (s *KeeperTestSuite) TestHasRole() { Addresses: []string{s.user1Addr.String()}, }, } - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, baseKey, baseRoles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, baseKey, baseRoles, "") s.Require().NoError(err) tests := []struct { @@ -387,7 +438,7 @@ func (s *KeeperTestSuite) TestGetRegistry() { Addresses: []string{s.user1Addr.String()}, }, } - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, baseKey, baseRoles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, baseKey, baseRoles, "") s.Require().NoError(err) tests := []struct { @@ -456,7 +507,7 @@ func (s *KeeperTestSuite) TestGetRegistries() { {AssetClassId: "eclass", NftId: "nft1"}, } for _, k := range keys { - s.Require().NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, k, roles)) + s.Require().NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, k, roles, "")) } // Helper to get key strings in order @@ -646,6 +697,323 @@ func (s *KeeperTestSuite) GenesisTest() { s.Require().Equal(genesis1, genesis2) } +// TestUnregisterNFT_RequiresControllerSignature verifies that when a CONTROLLER is set, the +// controller (not the NFT owner) must sign. When no controller is set, the NFT owner signs. +// This prevents an owner from bypassing policies via unregister+re-register while ensuring +// the controller can always unregister even if they don't own the NFT. +func (s *KeeperTestSuite) TestUnregisterNFT_RequiresControllerSignature() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: s.validNFT.Id, + } + require := s.Require() + msgServer := keeper.NewMsgServer(s.app.RegistryKeeper) + + // No controller set: NFT owner (user1) can unregister. + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{}, "")) + _, err := msgServer.UnregisterNFT(s.ctx, &types.MsgUnregisterNFT{Signer: s.user1, Key: key}) + require.NoError(err, "NFT owner must be able to unregister when no controller is set") + + // Register with user2 as CONTROLLER. user1 still owns the NFT. + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + }, "")) + + // user1 (NFT owner, not controller) is rejected. + _, err = msgServer.UnregisterNFT(s.ctx, &types.MsgUnregisterNFT{Signer: s.user1, Key: key}) + require.Error(err, "NFT owner without controller role must be rejected") + require.Contains(err.Error(), "unauthorized") + + // user2 (controller, not NFT owner) can unregister. + _, err = msgServer.UnregisterNFT(s.ctx, &types.MsgUnregisterNFT{Signer: s.user2, Key: key}) + require.NoError(err, "controller must be able to unregister even without owning the NFT") + + entry, err := s.app.RegistryKeeper.GetRegistry(s.ctx, key) + require.NoError(err) + require.Nil(entry, "registry entry must be gone after controller unregistration") +} + +// TestRegistryBulkUpdate_EnforcesRolePolicies verifies that RegistryBulkUpdate validates role +// changes through the authorization engine when updating existing entries, so it cannot bypass the +// same multi-party policies enforced by GrantRole / RevokeRole / SetRoles. +func (s *KeeperTestSuite) TestRegistryBulkUpdate_EnforcesRolePolicies() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: s.validNFT.Id, + } + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + + // Install the CONTROLLER policy so the authorization engine can enforce it. + require := s.Require() + require.NoError(s.app.RegistryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + })) + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.user1}}, + }, "")) + + // user1 (current controller + NFT owner) tries to transfer CONTROLLER to user2 without user2 + // co-signing. The CONTROLLER policy requires the incoming controller to sign; this must fail. + msgServer := keeper.NewMsgServer(s.app.RegistryKeeper) + _, err := msgServer.RegistryBulkUpdate(s.ctx, &types.MsgRegistryBulkUpdate{ + Signer: s.user1, + Entries: []types.RegistryEntry{ + { + Key: key, + Roles: []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.user2}}, + }, + }, + }, + }) + require.Error(err, "BulkUpdate should reject controller transfer without incoming controller signature") + require.Contains(err.Error(), "unauthorized") + + // The original entry must be unchanged. + entry, err := s.app.RegistryKeeper.GetRegistry(s.ctx, key) + require.NoError(err) + require.Equal([]string{s.user1}, entry.GetRoleAddrs(controllerRole), "controller must remain user1") +} + +// TestDeleteRegistry_ClearsPendingRoleChanges verifies that DeleteRegistry removes any pending +// role change records for the deleted entry so stale approvals cannot be replayed after +// re-registration. +func (s *KeeperTestSuite) TestDeleteRegistry_ClearsPendingRoleChanges() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: s.validNFT.Id, + } + require := s.Require() + + // Install the CONTROLLER policy so the authorization engine can enforce it. + require.NoError(s.app.RegistryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + })) + + // Register the NFT with user1 as CONTROLLER. + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }, "")) + + // Propose a controller change to user2. Because user2 (incoming controller) has not yet + // co-signed, this creates a pending change record rather than applying immediately. + changeID, applied, err := s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user1, key, []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + }) + require.NoError(err) + require.False(applied, "change should be pending, not immediately applied") + require.NotEmpty(changeID) + + // Confirm the pending change exists. + pending, _, err := s.app.RegistryKeeper.GetPendingRoleChanges(s.ctx, nil, key) + require.NoError(err) + require.Len(pending, 1, "pending change should exist before delete") + + // Delete the registry entry. + require.NoError(s.app.RegistryKeeper.DeleteRegistry(s.ctx, key)) + + // The pending change must be gone: without this cleanup, re-registration of the same NFT would + // allow the stale approvals to be replayed against the new entry. + pending, _, err = s.app.RegistryKeeper.GetPendingRoleChanges(s.ctx, nil, key) + require.NoError(err) + require.Empty(pending, "pending changes must be cleared after delete") +} + +// TestProposeRoleChange_LimitOnePerNFT verifies that only one pending role change can exist for a +// given NFT at a time. A second proposal for a different set of role updates must be rejected until +// the first is cancelled or applied. +func (s *KeeperTestSuite) TestProposeRoleChange_LimitOnePerNFT() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: s.validNFT.Id, + } + require := s.Require() + + // Install the CONTROLLER policy. + require.NoError(s.app.RegistryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + })) + + // Register with user1 as CONTROLLER. + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }, "")) + + // First proposal: transfer CONTROLLER to user2. Leaves a pending change (user2 must co-sign). + _, applied, err := s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user1, key, []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + }) + require.NoError(err) + require.False(applied) + + // Second proposal with different role updates must be rejected while the first is pending. + _, _, err = s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user1, key, []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }) + require.Error(err, "second conflicting proposal should be rejected") + require.Contains(err.Error(), "pending role change already exists") + + // Re-proposing the same role updates (same ID) is allowed — it acts as a co-approval. + _, _, err = s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user2, key, []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + }) + require.NoError(err, "co-approving the same pending change must be allowed") +} + +// TestCancelRoleChange verifies that a pending role change can be cancelled by its proposer and +// that non-proposers are rejected. +func (s *KeeperTestSuite) TestCancelRoleChange() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: s.validNFT.Id, + } + require := s.Require() + + require.NoError(s.app.RegistryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + })) + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }, "")) + + changeID, applied, err := s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user1, key, []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + }) + require.NoError(err) + require.False(applied) + + msgServer := keeper.NewMsgServer(s.app.RegistryKeeper) + + // Non-proposer cannot cancel. + _, err = msgServer.CancelRoleChange(s.ctx, &types.MsgCancelRoleChange{ + Signer: s.user2, + ChangeId: changeID, + }) + require.Error(err) + require.Contains(err.Error(), "unauthorized") + + // Proposer can cancel. + _, err = msgServer.CancelRoleChange(s.ctx, &types.MsgCancelRoleChange{ + Signer: s.user1, + ChangeId: changeID, + }) + require.NoError(err, "proposer must be able to cancel the pending change") + + // Change must be gone. + change, err := s.app.RegistryKeeper.GetPendingRoleChange(s.ctx, changeID) + require.NoError(err) + require.Nil(change, "pending change must not exist after cancellation") +} + +// TestPendingRoleChange_Expiry verifies that approvals on an expired pending change are rejected +// and the expired record is cleaned up. +func (s *KeeperTestSuite) TestPendingRoleChange_Expiry() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: s.validNFT.Id, + } + require := s.Require() + + require.NoError(s.app.RegistryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + PendingChangeExpiry: time.Hour, + })) + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }, "")) + + changeID, applied, err := s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user1, key, []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + }) + require.NoError(err) + require.False(applied) + + // Advance block time past the expiry. + s.ctx = s.ctx.WithBlockTime(s.ctx.BlockTime().Add(2 * time.Hour)) + + // Approval after expiry must be rejected and the record removed. + _, err = s.app.RegistryKeeper.ApproveRoleChange(s.ctx, s.user2, changeID) + require.Error(err, "approving an expired change must fail") + require.Contains(err.Error(), "pending role change not found") + + change, err := s.app.RegistryKeeper.GetPendingRoleChange(s.ctx, changeID) + require.NoError(err) + require.Nil(change, "expired change must be removed on failed approval") + + // After expiry cleans up via ApproveRoleChange, a new proposal must succeed. + _, _, err = s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user1, key, []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + }) + require.NoError(err, "new proposal must be accepted after expired record is cleaned up") +} + +// TestPendingRoleChange_ExpiredBlocksProposal verifies that an expired pending change is cleaned +// up eagerly when a new proposal is made, instead of blocking it indefinitely. +func (s *KeeperTestSuite) TestPendingRoleChange_ExpiredBlocksProposal() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: s.validNFT.Id, + } + require := s.Require() + + require.NoError(s.app.RegistryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + PendingChangeExpiry: time.Hour, + })) + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }, "")) + + // First proposal leaves a pending change that will expire. + _, _, err := s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user1, key, []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + }) + require.NoError(err) + + // Advance past expiry. + s.ctx = s.ctx.WithBlockTime(s.ctx.BlockTime().Add(2 * time.Hour)) + + // A new proposal with different role updates must succeed: the expired record is cleaned up + // eagerly rather than blocking the new proposal. + _, _, err = s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user1, key, []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }) + require.NoError(err, "proposal must succeed after expired pending change is cleaned up") +} + +// TestPendingRoleChange_ExpiryBypassViaPropose verifies that MsgProposeRoleChange also enforces +// expiry when reusing an existing pending record, preventing the expiry from being bypassed. +func (s *KeeperTestSuite) TestPendingRoleChange_ExpiryBypassViaPropose() { + key := &types.RegistryKey{ + AssetClassId: s.validNFTClass.Id, + NftId: s.validNFT.Id, + } + require := s.Require() + + require.NoError(s.app.RegistryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + PendingChangeExpiry: time.Hour, + })) + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }, "")) + + // Propose a change; user2 has not yet co-signed. + roleUpdates := []types.RoleUpdate{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + } + _, _, err := s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user1, key, roleUpdates) + require.NoError(err) + + // Advance past expiry. + s.ctx = s.ctx.WithBlockTime(s.ctx.BlockTime().Add(2 * time.Hour)) + + // Attempting to co-approve via ProposeRoleChange (same change ID) must also be rejected. + _, _, err = s.app.RegistryKeeper.ProposeRoleChange(s.ctx, s.user2, key, roleUpdates) + require.Error(err, "propose co-approval on expired change must fail") + require.Contains(err.Error(), "pending role change not found") +} + func (s *KeeperTestSuite) TestRegisterNFTMsgServer() { tests := []struct { name string @@ -755,3 +1123,247 @@ func (s *KeeperTestSuite) TestRegisterNFTMsgServer() { }) } } + +// TestAssociateRegistryClass_ControllerCanAssociate verifies that a CONTROLLER signer can +// associate a registry class on an existing entry. +func (s *KeeperTestSuite) TestAssociateRegistryClass_ControllerCanAssociate() { + require := s.Require() + key := &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} + + // Create a class whose asset_class_id matches the entry. + class := types.RegistryClass{ + RegistryClassId: "test-class", + AssetClassId: s.validNFTClass.Id, + Maintainer: s.user1, + RoleAuthorizations: nil, + } + require.NoError(s.app.RegistryKeeper.CreateRegistryClass(s.ctx, class)) + + // Register with a controller but no class yet. + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }, "")) + + msg := &types.MsgAssociateRegistryClass{ + Signer: s.user1, + Key: key, + RegistryClassId: "test-class", + } + _, err := keeper.NewMsgServer(s.app.RegistryKeeper).AssociateRegistryClass(s.ctx, msg) + require.NoError(err, "controller must be allowed to associate a registry class") + + entry, err := s.app.RegistryKeeper.GetRegistry(s.ctx, key) + require.NoError(err) + require.NotNil(entry) + require.Equal("test-class", entry.RegistryClassId, "registry_class_id must be updated") +} + +// TestAssociateRegistryClass_NFTOwnerCanAssociateWhenControllerSet verifies that the NFT owner can +// associate a registry class even when a separate controller is set — neither takes precedence. +func (s *KeeperTestSuite) TestAssociateRegistryClass_NFTOwnerCanAssociateWhenControllerSet() { + require := s.Require() + key := &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} + + class := types.RegistryClass{ + RegistryClassId: "test-class", + AssetClassId: s.validNFTClass.Id, + Maintainer: s.user1, + } + require.NoError(s.app.RegistryKeeper.CreateRegistryClass(s.ctx, class)) + + // user2 is the controller; user1 owns the NFT. + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user2}}, + }, "")) + + // user1 (NFT owner, not controller) must still be able to associate. + msg := &types.MsgAssociateRegistryClass{ + Signer: s.user1, + Key: key, + RegistryClassId: "test-class", + } + _, err := keeper.NewMsgServer(s.app.RegistryKeeper).AssociateRegistryClass(s.ctx, msg) + require.NoError(err, "NFT owner must be able to associate even when a controller is set") + + entry, err := s.app.RegistryKeeper.GetRegistry(s.ctx, key) + require.NoError(err) + require.Equal("test-class", entry.RegistryClassId) +} + + +// controller nor the NFT owner is rejected even when a controller is set on the entry. +func (s *KeeperTestSuite) TestAssociateRegistryClass_UnauthorizedSignerRejected() { + require := s.Require() + key := &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} + + class := types.RegistryClass{ + RegistryClassId: "test-class", + AssetClassId: s.validNFTClass.Id, + Maintainer: s.user1, + } + require.NoError(s.app.RegistryKeeper.CreateRegistryClass(s.ctx, class)) + + // user1 is the controller AND NFT owner; user2 is neither. + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.user1}}, + }, "")) + + msg := &types.MsgAssociateRegistryClass{ + Signer: s.user2, + Key: key, + RegistryClassId: "test-class", + } + _, err := keeper.NewMsgServer(s.app.RegistryKeeper).AssociateRegistryClass(s.ctx, msg) + require.Error(err, "signer who is neither controller nor NFT owner must be rejected") +} + +// TestAssociateRegistryClass_NFTOwnerCanAssociateWithoutController verifies that the NFT owner can +// associate a class when no controller is set on the entry. +func (s *KeeperTestSuite) TestAssociateRegistryClass_NFTOwnerCanAssociateWithoutController() { + require := s.Require() + key := &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} + + class := types.RegistryClass{ + RegistryClassId: "test-class", + AssetClassId: s.validNFTClass.Id, + Maintainer: s.user1, + } + require.NoError(s.app.RegistryKeeper.CreateRegistryClass(s.ctx, class)) + + // No controller set — entry created by user1 who also owns the NFT. + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{}, "")) + + msg := &types.MsgAssociateRegistryClass{ + Signer: s.user1, + Key: key, + RegistryClassId: "test-class", + } + _, err := keeper.NewMsgServer(s.app.RegistryKeeper).AssociateRegistryClass(s.ctx, msg) + require.NoError(err, "NFT owner must be allowed when no controller is set") + + entry, err := s.app.RegistryKeeper.GetRegistry(s.ctx, key) + require.NoError(err) + require.Equal("test-class", entry.RegistryClassId) +} + +// TestAssociateRegistryClass_ScopeDataOwnerCanAssociate verifies that a scope data-owner party can +// associate a registry class when the NFT is a Provenance Metadata Scope. +func (s *KeeperTestSuite) TestAssociateRegistryClass_ScopeDataOwnerCanAssociate() { + require := s.Require() + + // Create a real Provenance Metadata Scope. + scopeID := metadatatypes.ScopeMetadataAddress(uuid.New()) + scope := metadatatypes.NewScope( + scopeID, + metadatatypes.MetadataAddress{}, // no spec required for this test + []metadatatypes.Party{ + {Address: s.user1, Role: metadatatypes.PartyType_PARTY_TYPE_OWNER}, + }, + nil, // no data access + "", // no value owner + false, // no party rollup + ) + require.NoError(s.app.MetadataKeeper.SetScope(s.ctx, *scope)) + + // The "asset class" for a Scope is a scope-spec address; for this test we reuse the existing + // nft class and rely on the fact that the registry module validates the NFT exists via scope + // lookup, not class lookup for scope-type NFTs. Use the scope bech32 as the nftID. + scopeBech32 := scopeID.String() + + // We need an asset_class_id for the RegistryKey — use the NFT class id as a stand-in. + assetClassID := s.validNFTClass.Id + key := &types.RegistryKey{AssetClassId: assetClassID, NftId: scopeBech32} + + class := types.RegistryClass{ + RegistryClassId: "scope-class", + AssetClassId: assetClassID, + Maintainer: s.user1, + } + require.NoError(s.app.RegistryKeeper.CreateRegistryClass(s.ctx, class)) + + // Register without controller — no scope spec check needed for this path. + require.NoError(s.app.RegistryKeeper.SetRegistry(s.ctx, types.RegistryEntry{ + Key: key, + Roles: []types.RolesEntry{}, + RegistryClassId: "", + })) + + msg := &types.MsgAssociateRegistryClass{ + Signer: s.user1, // user1 is a scope Owner party (data owner) + Key: key, + RegistryClassId: "scope-class", + } + _, err := keeper.NewMsgServer(s.app.RegistryKeeper).AssociateRegistryClass(s.ctx, msg) + require.NoError(err, "scope data owner must be allowed to associate a registry class") +} + +// TestAssociateRegistryClass_NonOwnerScopePartyRejected verifies that a scope party whose role is +// not PARTY_TYPE_OWNER is rejected, even though they appear in scope.Owners. +func (s *KeeperTestSuite) TestAssociateRegistryClass_NonOwnerScopePartyRejected() { + require := s.Require() + + scopeID := metadatatypes.ScopeMetadataAddress(uuid.New()) + scope := metadatatypes.NewScope( + scopeID, + metadatatypes.MetadataAddress{}, + []metadatatypes.Party{ + // user1 is an originator — not a data owner. + {Address: s.user1, Role: metadatatypes.PartyType_PARTY_TYPE_ORIGINATOR}, + }, + nil, "", false, + ) + require.NoError(s.app.MetadataKeeper.SetScope(s.ctx, *scope)) + + assetClassID := s.validNFTClass.Id + key := &types.RegistryKey{AssetClassId: assetClassID, NftId: scopeID.String()} + + class := types.RegistryClass{ + RegistryClassId: "scope-class", + AssetClassId: assetClassID, + Maintainer: s.user1, + } + require.NoError(s.app.RegistryKeeper.CreateRegistryClass(s.ctx, class)) + require.NoError(s.app.RegistryKeeper.SetRegistry(s.ctx, types.RegistryEntry{ + Key: key, Roles: []types.RolesEntry{}, + })) + + msg := &types.MsgAssociateRegistryClass{ + Signer: s.user1, + Key: key, + RegistryClassId: "scope-class", + } + _, err := keeper.NewMsgServer(s.app.RegistryKeeper).AssociateRegistryClass(s.ctx, msg) + require.Error(err, "scope party with non-OWNER role must be rejected") +} + + +// rejected at ValidateBasic. +func (s *KeeperTestSuite) TestAssociateRegistryClass_EmptyClassIdRejected() { + require := s.Require() + key := &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} + require.NoError(s.app.RegistryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{}, "")) + + msg := types.MsgAssociateRegistryClass{ + Signer: s.user1, + Key: key, + RegistryClassId: "", + } + err := msg.ValidateBasic() + require.Error(err, "empty registry_class_id must be rejected by ValidateBasic") + require.Contains(err.Error(), "registry_class_id") +} + +// TestAssociateRegistryClass_EntryNotFound verifies that the handler returns an error when there +// is no existing registry entry for the given key. +func (s *KeeperTestSuite) TestAssociateRegistryClass_EntryNotFound() { + require := s.Require() + key := &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: "non-existent-nft"} + + msg := &types.MsgAssociateRegistryClass{ + Signer: s.user1, + Key: key, + RegistryClassId: "some-class", + } + _, err := keeper.NewMsgServer(s.app.RegistryKeeper).AssociateRegistryClass(s.ctx, msg) + require.Error(err, "must return an error when the registry entry does not exist") +} diff --git a/x/registry/keeper/keys.go b/x/registry/keeper/keys.go index 282fb67bed..d2e8c479e8 100644 --- a/x/registry/keeper/keys.go +++ b/x/registry/keeper/keys.go @@ -1,5 +1,8 @@ package keeper var ( - registryPrefix = []byte{0x01} + registryPrefix = []byte{0x01} + pendingRoleChangePrefix = []byte{0x02} + registryClassPrefix = []byte{0x03} + paramsPrefix = []byte{0x04} ) diff --git a/x/registry/keeper/msg_server.go b/x/registry/keeper/msg_server.go index 85ae849ead..776a9a214e 100644 --- a/x/registry/keeper/msg_server.go +++ b/x/registry/keeper/msg_server.go @@ -3,6 +3,7 @@ package keeper import ( "context" "fmt" + "slices" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/gogoproto/proto" @@ -34,8 +35,13 @@ func (k msgServer) RegisterNFT(ctx context.Context, msg *types.MsgRegisterNFT) ( return nil, err } + // If a registry class is referenced, it must exist and match this entry's asset class. + if err := k.validateRegistryClassForEntry(ctx, msg.RegistryClassId, msg.Key.AssetClassId); err != nil { + return nil, err + } + // Store the registry in state. - err := k.CreateRegistry(ctx, msg.Key, msg.Roles) + err := k.CreateRegistry(ctx, msg.Key, msg.Roles, msg.RegistryClassId) if err != nil { return nil, err } @@ -46,21 +52,45 @@ func (k msgServer) RegisterNFT(ctx context.Context, msg *types.MsgRegisterNFT) ( // GrantRole grants a role to one or more addresses. // This adds the specified addresses to the role for the given registry key. func (k msgServer) GrantRole(ctx context.Context, msg *types.MsgGrantRole) (*types.MsgGrantRoleResponse, error) { - // ensure the registry exists - if err := k.ValidateRegistryExists(ctx, msg.Key); err != nil { + // Ensure the registry exists and fetch the current entry for auth checks. + entry, err := k.GetRegistry(ctx, msg.Key) + if err != nil { return nil, err } + if entry == nil { + return nil, types.NewErrCodeRegistryNotFound(msg.Key.String()) + } - // Validate that the signer owns the NFT - if err := k.ValidateNFTOwner(ctx, &msg.Key.AssetClassId, &msg.Key.NftId, msg.Signer); err != nil { + roleAuths, err := k.roleAuthorizationsForEntry(ctx, entry) + if err != nil { return nil, err } + if roleAuth, ok := roleAuths[msg.Role]; ok { + // Policy-based path: the incoming addresses are the "new" assignment. A single signer must + // satisfy the policy on its own; multi-party changes go through ProposeRoleChange. + if err := k.Keeper.ValidateRoleChangeAuthorization(ctx, roleAuth, entry, msg.Addresses, []string{msg.Signer}); err != nil { + return nil, err + } + } else { + // Legacy fallback: the signer must own the NFT. + if err := k.ValidateNFTOwner(ctx, &msg.Key.AssetClassId, &msg.Key.NftId, msg.Signer); err != nil { + return nil, err + } + } // Grant the role to the addresses. - err := k.Keeper.GrantRole(ctx, msg.Key, msg.Role, msg.Addresses) + err = k.Keeper.GrantRole(ctx, msg.Key, msg.Role, msg.Addresses) + if err != nil { + return nil, err + } + + signers, err := k.roleChangeSigners(ctx, entry, msg.Role, msg.Addresses, []string{msg.Signer}) if err != nil { return nil, err } + if err := k.emitRoleUpdated(ctx, entry, msg.Role, signers); err != nil { + return nil, err + } return &types.MsgGrantRoleResponse{}, nil } @@ -68,31 +98,238 @@ func (k msgServer) GrantRole(ctx context.Context, msg *types.MsgGrantRole) (*typ // RevokeRole revokes a role from one or more addresses. // This removes the specified addresses from the role for the given registry key. func (k msgServer) RevokeRole(ctx context.Context, msg *types.MsgRevokeRole) (*types.MsgRevokeRoleResponse, error) { - // ensure the registry exists - if err := k.ValidateRegistryExists(ctx, msg.Key); err != nil { + // Ensure the registry exists and fetch the current entry for auth checks. + entry, err := k.GetRegistry(ctx, msg.Key) + if err != nil { return nil, err } + if entry == nil { + return nil, types.NewErrCodeRegistryNotFound(msg.Key.String()) + } - // Validate that the signer owns the NFT - if err := k.ValidateNFTOwner(ctx, &msg.Key.AssetClassId, &msg.Key.NftId, msg.Signer); err != nil { + roleAuths, err := k.roleAuthorizationsForEntry(ctx, entry) + if err != nil { return nil, err } + if roleAuth, ok := roleAuths[msg.Role]; ok { + // Policy-based path. For revoke, no new addresses are being assigned. A single signer must + // satisfy the policy on its own; multi-party changes go through ProposeRoleChange. + if err := k.Keeper.ValidateRoleChangeAuthorization(ctx, roleAuth, entry, nil, []string{msg.Signer}); err != nil { + return nil, err + } + } else { + // Legacy fallback: the signer must own the NFT. + if err := k.ValidateNFTOwner(ctx, &msg.Key.AssetClassId, &msg.Key.NftId, msg.Signer); err != nil { + return nil, err + } + } // Revoke the role from the addresses. - err := k.Keeper.RevokeRole(ctx, msg.Key, msg.Role, msg.Addresses) + err = k.Keeper.RevokeRole(ctx, msg.Key, msg.Role, msg.Addresses) + if err != nil { + return nil, err + } + + signers, err := k.roleChangeSigners(ctx, entry, msg.Role, nil, []string{msg.Signer}) if err != nil { return nil, err } + if err := k.emitRoleUpdated(ctx, entry, msg.Role, signers); err != nil { + return nil, err + } return &types.MsgRevokeRoleResponse{}, nil } +// SetRoles atomically sets the desired state for one or more roles on a registry entry. +// Each role update specifies a role and the complete desired set of addresses for that role. +// An empty address list clears the role. +func (k msgServer) SetRoles(ctx context.Context, msg *types.MsgSetRoles) (*types.MsgSetRolesResponse, error) { + // Ensure the registry exists and fetch the current entry for auth checks. + entry, err := k.GetRegistry(ctx, msg.Key) + if err != nil { + return nil, err + } + if entry == nil { + return nil, types.NewErrCodeRegistryNotFound(msg.Key.String()) + } + + roleAuths, err := k.roleAuthorizationsForEntry(ctx, entry) + if err != nil { + return nil, err + } + for _, update := range msg.RoleUpdates { + if roleAuth, ok := roleAuths[update.Role]; ok { + // ASSIGNMENT_NEW resolves only the newly-added addresses, so authorize against the + // additions relative to the current state (not the full desired set). A single signer + // must satisfy the policy on its own; multi-party changes go through ProposeRoleChange. + newAddrs := additions(entry.GetRoleAddrs(update.Role), update.Addresses) + if err := k.Keeper.ValidateRoleChangeAuthorization(ctx, roleAuth, entry, newAddrs, []string{msg.Signer}); err != nil { + return nil, err + } + } else { + // Legacy fallback: the signer must own the NFT. + if err := k.ValidateNFTOwner(ctx, &msg.Key.AssetClassId, &msg.Key.NftId, msg.Signer); err != nil { + return nil, err + } + } + } + + if err := k.Keeper.SetRoles(ctx, msg.Key, msg.RoleUpdates); err != nil { + return nil, err + } + + for _, update := range msg.RoleUpdates { + newAddrs := additions(entry.GetRoleAddrs(update.Role), update.Addresses) + signers, err := k.roleChangeSigners(ctx, entry, update.Role, newAddrs, []string{msg.Signer}) + if err != nil { + return nil, err + } + if err := k.emitRoleUpdated(ctx, entry, update.Role, signers); err != nil { + return nil, err + } + } + + return &types.MsgSetRolesResponse{}, nil +} + +// ProposeRoleChange opens a pending role change that accumulates single-signer approvals and +// auto-applies once the role's authorization policy is satisfied. +func (k msgServer) ProposeRoleChange(ctx context.Context, msg *types.MsgProposeRoleChange) (*types.MsgProposeRoleChangeResponse, error) { + id, applied, err := k.Keeper.ProposeRoleChange(ctx, msg.Signer, msg.Key, msg.RoleUpdates) + if err != nil { + return nil, err + } + return &types.MsgProposeRoleChangeResponse{ChangeId: id, Applied: applied}, nil +} + +// ApproveRoleChange records a single-signer approval for a pending role change and auto-applies +// it once the role's authorization policy is satisfied. +func (k msgServer) ApproveRoleChange(ctx context.Context, msg *types.MsgApproveRoleChange) (*types.MsgApproveRoleChangeResponse, error) { + applied, err := k.Keeper.ApproveRoleChange(ctx, msg.Signer, msg.ChangeId) + if err != nil { + return nil, err + } + return &types.MsgApproveRoleChangeResponse{Applied: applied}, nil +} + +// CancelRoleChange cancels an open pending role change. Only the original proposer may cancel. +func (k msgServer) CancelRoleChange(ctx context.Context, msg *types.MsgCancelRoleChange) (*types.MsgCancelRoleChangeResponse, error) { + change, err := k.GetPendingRoleChange(ctx, msg.ChangeId) + if err != nil { + return nil, err + } + if change == nil { + return nil, types.NewErrCodePendingChangeNotFound(msg.ChangeId) + } + if change.Proposer != msg.Signer { + return nil, types.NewErrCodeUnauthorized("only the original proposer may cancel a pending role change") + } + if err := k.RemovePendingRoleChange(ctx, msg.ChangeId); err != nil { + return nil, err + } + k.EmitEvent(ctx, types.NewEventRoleChangeCancelled(msg.ChangeId, msg.Signer)) + return &types.MsgCancelRoleChangeResponse{}, nil +} + +// AssociateRegistryClass associates or updates the registry class on an existing entry. +// The entry must already exist; use RegisterNFT with a registry_class_id to set it on creation. +// Auth: CONTROLLER or scope data owner (if NFT is a Metadata Scope) or NFT owner — either is sufficient. +func (k msgServer) AssociateRegistryClass(ctx context.Context, msg *types.MsgAssociateRegistryClass) (*types.MsgAssociateRegistryClassResponse, error) { + entry, err := k.GetRegistry(ctx, msg.Key) + if err != nil { + return nil, fmt.Errorf("could not get registry entry: %w", err) + } + if entry == nil { + return nil, types.NewErrCodeRegistryNotFound(msg.Key.NftId) + } + + // Either a CONTROLLER or the scope data owner / NFT owner may associate a registry class. + // Neither takes precedence — the first matching condition is sufficient. + isController := slices.Contains(entry.GetRoleAddrs(types.RegistryRole_REGISTRY_ROLE_CONTROLLER), msg.Signer) + if !isController { + if err := k.validateAssociateRegistryClassSigner(ctx, &msg.Key.AssetClassId, &msg.Key.NftId, msg.Signer); err != nil { + return nil, err + } + } + + if err := k.validateRegistryClassForEntry(ctx, msg.RegistryClassId, entry.Key.AssetClassId); err != nil { + return nil, err + } + + entry.RegistryClassId = msg.RegistryClassId + if err := k.SetRegistry(ctx, *entry); err != nil { + return nil, err + } + + return &types.MsgAssociateRegistryClassResponse{}, nil +} + +// CreateRegistryClass creates a new registry class defining asset class-level authorization rules. +func (k msgServer) CreateRegistryClass(ctx context.Context, msg *types.MsgCreateRegistryClass) (*types.MsgCreateRegistryClassResponse, error) { + class := types.RegistryClass{ + RegistryClassId: msg.RegistryClassId, + AssetClassId: msg.AssetClassId, + Maintainer: msg.Maintainer, + RoleAuthorizations: msg.RoleAuthorizations, + } + if err := k.Keeper.CreateRegistryClass(ctx, class); err != nil { + return nil, err + } + return &types.MsgCreateRegistryClassResponse{}, nil +} + +// UpdateRegistryClassRoleAuthorization replaces the authorization rules for an existing registry +// class. Only the current maintainer may update the rules. +func (k msgServer) UpdateRegistryClassRoleAuthorization(ctx context.Context, msg *types.MsgUpdateRegistryClassRoleAuthorization) (*types.MsgUpdateRegistryClassRoleAuthorizationResponse, error) { + if err := k.Keeper.UpdateRegistryClassRoleAuthorization(ctx, msg.Signer, msg.RegistryClassId, msg.RoleAuthorizations); err != nil { + return nil, err + } + return &types.MsgUpdateRegistryClassRoleAuthorizationResponse{}, nil +} + +// UpdateParams is a governance proposal endpoint for updating the registry module's params, +// including the default role authorization policies. +func (k msgServer) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { + if err := k.ValidateAuthority(msg.Authority); err != nil { + return nil, err + } + + if err := k.SetParams(ctx, msg.Params); err != nil { + return nil, err + } + + k.EmitEvent(ctx, types.NewEventParamsUpdated()) + return &types.MsgUpdateParamsResponse{}, nil +} + // UnregisterNFT unregisters an NFT from the registry. // This removes the entire registry entry and associated data for the specified key. func (k msgServer) UnregisterNFT(ctx context.Context, msg *types.MsgUnregisterNFT) (*types.MsgUnregisterNFTResponse, error) { - // Validate that the signer owns the NFT - if err := k.ValidateNFTOwner(ctx, &msg.Key.AssetClassId, &msg.Key.NftId, msg.Signer); err != nil { - return nil, err + entry, err := k.GetRegistry(ctx, msg.Key) + if err != nil { + return nil, fmt.Errorf("could not get registry entry: %w", err) + } + + // If a CONTROLLER is set, the CONTROLLER must sign. This prevents an NFT owner from bypassing + // multi-party role policies by unregistering and re-registering with new roles. The controller + // does not need to own the NFT — the controller role is authoritative for this action when set. + // If no controller is set, fall back to NFT-ownership authorization. + if entry != nil { + controllers := entry.GetRoleAddrs(types.RegistryRole_REGISTRY_ROLE_CONTROLLER) + if len(controllers) > 0 { + if !slices.Contains(controllers, msg.Signer) { + return nil, types.NewErrCodeUnauthorized("signer is not the controller") + } + } else { + if err := k.ValidateNFTOwner(ctx, &msg.Key.AssetClassId, &msg.Key.NftId, msg.Signer); err != nil { + return nil, err + } + } + } else { + if err := k.ValidateNFTOwner(ctx, &msg.Key.AssetClassId, &msg.Key.NftId, msg.Signer); err != nil { + return nil, err + } } if err := k.DeleteRegistry(ctx, msg.Key); err != nil { @@ -124,12 +361,58 @@ func (k msgServer) RegistryBulkUpdate(ctx context.Context, msg *types.MsgRegistr } } + // If a registry class is referenced, it must exist and match this entry's asset class. + if err := k.validateRegistryClassForEntry(ctx, entry.RegistryClassId, entry.Key.AssetClassId); err != nil { + return nil, fmt.Errorf("[%d]: %w", i, err) + } + // Get the original registry, so we know what we're updating. orig, err := k.GetRegistry(ctx, entry.Key) if err != nil { return nil, fmt.Errorf("could not get existing registry entry [%d]: %w", i, err) } + // When updating an existing entry, validate each role change through the authorization + // engine so that RegistryBulkUpdate cannot bypass the multi-party policies enforced by + // GrantRole, RevokeRole, and SetRoles. Authority addresses are exempt from this check (they + // also bypass NFT-ownership validation above). New registrations (orig == nil) are treated + // like RegisterNFT: NFT ownership was already verified, so initial role seeding is allowed. + if orig != nil && msg.Signer != authority1 && msg.Signer != authority2 { + roleAuths, err := k.roleAuthorizationsForEntry(ctx, orig) + if err != nil { + return nil, fmt.Errorf("[%d] could not get role authorizations: %w", i, err) + } + // Validate roles being set or changed to a new desired state. + for _, roleEntry := range entry.Roles { + if roleAuth, ok := roleAuths[roleEntry.Role]; ok { + // Pass only newly added addresses (not the full list) to match the semantics of + // GrantRole / SetRoles, where ASSIGNMENT_NEW* policies are evaluated against + // addresses that are incoming — not those already holding the role. + newAddrs := additions(orig.GetRoleAddrs(roleEntry.Role), roleEntry.Addresses) + if err := k.Keeper.ValidateRoleChangeAuthorization(ctx, roleAuth, orig, newAddrs, []string{msg.Signer}); err != nil { + return nil, fmt.Errorf("[%d] unauthorized update for role %s: %w", i, roleEntry.Role.ShortString(), err) + } + } + } + // Validate roles being cleared (present in orig but absent from the new entry). + for _, origRole := range orig.Roles { + hasInNew := false + for _, newRole := range entry.Roles { + if newRole.Role == origRole.Role { + hasInNew = true + break + } + } + if !hasInNew { + if roleAuth, ok := roleAuths[origRole.Role]; ok { + if err := k.Keeper.ValidateRoleChangeAuthorization(ctx, roleAuth, orig, nil, []string{msg.Signer}); err != nil { + return nil, fmt.Errorf("[%d] unauthorized removal of role %s: %w", i, origRole.Role.ShortString(), err) + } + } + } + } + } + // Store the registry. err = k.Registry.Set(ctx, entry.Key.CollKey(), entry) if err != nil { diff --git a/x/registry/keeper/nft.go b/x/registry/keeper/nft.go index 78c10abf16..a81ae5a19e 100644 --- a/x/registry/keeper/nft.go +++ b/x/registry/keeper/nft.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" + metadatatypes "github.com/provenance-io/provenance/x/metadata/types" "github.com/provenance-io/provenance/x/registry/types" ) @@ -59,7 +60,27 @@ func (k Keeper) GetNFTOwner(ctx context.Context, assetClassID, nftID *string) sd return k.NFTKeeper.GetOwner(ctx, *assetClassID, *nftID) } -// ValidateNFTOwner returns nil if the described NFT is owned by the expOwner. +// validateAssociateRegistryClassSigner checks whether signer is authorized at the NFT-ownership +// tier for AssociateRegistryClass. For Metadata Scopes the signer must be one of the scope's +// data-owner parties; for all other NFTs the signer must be the value/NFT owner. +func (k Keeper) validateAssociateRegistryClassSigner(ctx context.Context, assetClassID, nftID *string, signer string) error { + metadataAddress, isMetadataScope := types.MetadataScopeID(*nftID) + if isMetadataScope { + sdkCtx := sdk.UnwrapSDKContext(ctx) + scope, found := k.MetadataKeeper.GetScope(sdkCtx, metadataAddress) + if !found { + return types.NewErrCodeNFTNotFound(*nftID) + } + for _, party := range scope.Owners { + if party.Address == signer && party.Role == metadatatypes.PartyType_PARTY_TYPE_OWNER { + return nil + } + } + return types.NewErrCodeUnauthorized("signer is not a data owner (PARTY_TYPE_OWNER) of the scope") + } + return k.ValidateNFTOwner(ctx, assetClassID, nftID, signer) +} + // Returns an error if owned by someone else, or if the NFT doesn't exist. func (k Keeper) ValidateNFTOwner(ctx context.Context, assetClassID, nftID *string, expOwner string) error { nftOwner := k.GetNFTOwner(ctx, assetClassID, nftID) diff --git a/x/registry/keeper/params.go b/x/registry/keeper/params.go new file mode 100644 index 0000000000..b92f153033 --- /dev/null +++ b/x/registry/keeper/params.go @@ -0,0 +1,50 @@ +package keeper + +import ( + "context" + "errors" + "fmt" + "strings" + + "cosmossdk.io/collections" + + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/provenance-io/provenance/x/registry/types" +) + +// GetAuthority returns the module's governance authority address. +func (k Keeper) GetAuthority() string { + return k.authority +} + +// IsAuthority returns true if the provided bech32 address is the module's authority. +func (k Keeper) IsAuthority(addr string) bool { + return strings.EqualFold(k.authority, addr) +} + +// ValidateAuthority returns an error if the provided address is not the module's authority. +func (k Keeper) ValidateAuthority(addr string) error { + if !k.IsAuthority(addr) { + return govtypes.ErrInvalidSigner.Wrapf("expected %q got %q", k.GetAuthority(), addr) + } + return nil +} + +// GetParams returns the registry module params. If no params have been set, it returns the module +// defaults. +func (k Keeper) GetParams(ctx context.Context) types.Params { + params, err := k.Params.Get(ctx) + if err != nil { + if errors.Is(err, collections.ErrNotFound) { + return types.DefaultParams() + } + panic(fmt.Errorf("could not get registry params: %w", err)) + } + return params +} + +// SetParams stores the registry module params in state. +func (k Keeper) SetParams(ctx context.Context, params types.Params) error { + return k.Params.Set(ctx, params) +} diff --git a/x/registry/keeper/params_acceptance_test.go b/x/registry/keeper/params_acceptance_test.go new file mode 100644 index 0000000000..50f6785382 --- /dev/null +++ b/x/registry/keeper/params_acceptance_test.go @@ -0,0 +1,191 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "cosmossdk.io/x/nft" + nftkeeper "cosmossdk.io/x/nft/keeper" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/provenance-io/provenance/app" + "github.com/provenance-io/provenance/x/registry/keeper" + "github.com/provenance-io/provenance/x/registry/types" +) + +// ParamsAcceptanceTestSuite covers Phase C2: the registry module's governance-managed params. +// The params hold the default role authorization policies, which form the middle tier of the +// two-tier resolution (registry class policy -> module params default -> NFT-owner fallback). +type ParamsAcceptanceTestSuite struct { + suite.Suite + + app *app.App + ctx sdk.Context + + registryKeeper keeper.Keeper + nftKeeper nftkeeper.Keeper + msgServer types.MsgServer + + authority string + + nftClass nft.Class + + nftOwner string + controller string + stranger string + grantee string +} + +func TestParamsAcceptanceTestSuite(t *testing.T) { + suite.Run(t, new(ParamsAcceptanceTestSuite)) +} + +func (s *ParamsAcceptanceTestSuite) SetupTest() { + s.app = app.Setup(s.T()) + s.ctx = s.app.BaseApp.NewContextLegacy(false, cmtproto.Header{Time: time.Now()}).WithBlockTime(time.Now()) + + s.nftKeeper = s.app.NFTKeeper + s.registryKeeper = s.app.RegistryKeeper + s.msgServer = keeper.NewMsgServer(s.registryKeeper) + + s.authority = authtypes.NewModuleAddress(govtypes.ModuleName).String() + + s.nftOwner = genAddr() + s.controller = genAddr() + s.stranger = genAddr() + s.grantee = genAddr() + + s.nftClass = nft.Class{Id: "params-test-nft-class"} + s.nftKeeper.SaveClass(s.ctx, s.nftClass) +} + +func (s *ParamsAcceptanceTestSuite) mintNFT(id string) *types.RegistryKey { + n := nft.NFT{ClassId: s.nftClass.Id, Id: id} + ownerAddr, err := sdk.AccAddressFromBech32(s.nftOwner) + s.Require().NoError(err) + s.Require().NoError(s.nftKeeper.Mint(s.ctx, n, ownerAddr)) + return &types.RegistryKey{AssetClassId: s.nftClass.Id, NftId: id} +} + +// TestDefaultParams confirms the module starts with no role policies, preserving the original +// NFT-owner-only authorization behavior. The CONTROLLER policy is only an example, not a default. +func (s *ParamsAcceptanceTestSuite) TestDefaultParams() { + params := s.registryKeeper.GetParams(s.ctx) + s.Require().NoError(params.Validate()) + s.Require().Empty(params.RoleAuthorizations, "default params should define no role policies") +} + +// TestUpdateParamsAuthority confirms only the governance authority may update params. +func (s *ParamsAcceptanceTestSuite) TestUpdateParamsAuthority() { + newParams := types.Params{ + RoleAuthorizations: []types.RoleAuthorization{servicerRoleAuthorization()}, + } + + s.Run("reject: non-authority signer", func() { + _, err := s.msgServer.UpdateParams(s.ctx, &types.MsgUpdateParams{ + Authority: s.stranger, + Params: newParams, + }) + s.Require().Error(err) + s.Require().ErrorContains(err, "expected") + }) + + s.Run("success: governance authority", func() { + _, err := s.msgServer.UpdateParams(s.ctx, &types.MsgUpdateParams{ + Authority: s.authority, + Params: newParams, + }) + s.Require().NoError(err) + + got := s.registryKeeper.GetParams(s.ctx) + s.Require().Len(got.RoleAuthorizations, 1) + s.Require().Equal(types.RegistryRole_REGISTRY_ROLE_SERVICER, got.RoleAuthorizations[0].Role) + }) +} + +// TestParamsDrivenDefaultTier proves that the middle (params) tier of the two-tier resolution is +// governance-managed: changing params changes the default authorization for entries with no class. +func (s *ParamsAcceptanceTestSuite) TestParamsDrivenDefaultTier() { + roles := []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.controller}}, + } + + // Before changing params: SERVICER has no default policy, so granting it falls back to + // NFT-owner authorization. The controller (not the owner) cannot grant it. + keyBefore := s.mintNFT("nft-before-params") + _, err := s.msgServer.RegisterNFT(s.ctx, &types.MsgRegisterNFT{ + Signer: s.nftOwner, + Key: keyBefore, + Roles: roles, + }) + s.Require().NoError(err) + + _, err = s.msgServer.GrantRole(s.ctx, &types.MsgGrantRole{ + Signer: s.controller, + Key: keyBefore, + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{s.grantee}, + }) + s.Require().Error(err, "without a SERVICER default policy, controller cannot grant SERVICER") + + // Governance adds a SERVICER default policy (satisfied by the current controller). + _, err = s.msgServer.UpdateParams(s.ctx, &types.MsgUpdateParams{ + Authority: s.authority, + Params: types.Params{ + RoleAuthorizations: []types.RoleAuthorization{servicerRoleAuthorization()}, + }, + }) + s.Require().NoError(err) + + // After changing params: the same operation on a fresh (classless) entry now uses the new + // default policy, so the controller can grant SERVICER. + keyAfter := s.mintNFT("nft-after-params") + _, err = s.msgServer.RegisterNFT(s.ctx, &types.MsgRegisterNFT{ + Signer: s.nftOwner, + Key: keyAfter, + Roles: roles, + }) + s.Require().NoError(err) + + _, err = s.msgServer.GrantRole(s.ctx, &types.MsgGrantRole{ + Signer: s.controller, + Key: keyAfter, + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{s.grantee}, + }) + s.Require().NoError(err, "with a SERVICER default policy, controller can grant SERVICER") + + hasRole, err := s.registryKeeper.HasRole(s.ctx, keyAfter, types.RegistryRole_REGISTRY_ROLE_SERVICER, s.grantee) + s.Require().NoError(err) + s.Require().True(hasRole) +} + +// TestParamsGenesisRoundTrip verifies params survive an export/import cycle. +func (s *ParamsAcceptanceTestSuite) TestParamsGenesisRoundTrip() { + _, err := s.msgServer.UpdateParams(s.ctx, &types.MsgUpdateParams{ + Authority: s.authority, + Params: types.Params{ + RoleAuthorizations: []types.RoleAuthorization{servicerRoleAuthorization()}, + }, + }) + s.Require().NoError(err) + + exported := s.registryKeeper.ExportGenesis(s.ctx) + s.Require().NoError(exported.Validate()) + s.Require().Len(exported.Params.RoleAuthorizations, 1) + + freshApp := app.Setup(s.T()) + freshCtx := freshApp.BaseApp.NewContextLegacy(false, cmtproto.Header{Time: time.Now()}).WithBlockTime(time.Now()) + freshApp.RegistryKeeper.InitGenesis(freshCtx, exported) + + got := freshApp.RegistryKeeper.GetParams(freshCtx) + s.Require().Len(got.RoleAuthorizations, 1) + s.Require().Equal(types.RegistryRole_REGISTRY_ROLE_SERVICER, got.RoleAuthorizations[0].Role) +} diff --git a/x/registry/keeper/participant_role_policies_acceptance_test.go b/x/registry/keeper/participant_role_policies_acceptance_test.go new file mode 100644 index 0000000000..d8606c0f35 --- /dev/null +++ b/x/registry/keeper/participant_role_policies_acceptance_test.go @@ -0,0 +1,665 @@ +package keeper_test + +import ( + "os" + "path/filepath" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "cosmossdk.io/x/nft" + nftkeeper "cosmossdk.io/x/nft/keeper" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/provenance-io/provenance/app" + "github.com/provenance-io/provenance/x/registry/keeper" + "github.com/provenance-io/provenance/x/registry/types" +) + +// ParticipantRolePoliciesAcceptanceTestSuite proves that the participant role policies described in +// the requirements (§"Participant Roles") are expressible as ordinary +// RegistryClass.role_authorizations data and are correctly evaluated by the policy engine — without +// any hard-coded, per-role chain logic. The same policies double as the example fixture shipped in +// x/registry/spec/examples/example_registry_class.json. +type ParticipantRolePoliciesAcceptanceTestSuite struct { + suite.Suite + + app *app.App + ctx sdk.Context + + registryKeeper keeper.Keeper + nftKeeper nftkeeper.Keeper + msgServer types.MsgServer + + nftClass nft.Class + + maintainer string + nftOwner string +} + +func TestParticipantRolePoliciesAcceptanceTestSuite(t *testing.T) { + suite.Run(t, new(ParticipantRolePoliciesAcceptanceTestSuite)) +} + +const exampleClassID = "loan-registry-v1" + +func (s *ParticipantRolePoliciesAcceptanceTestSuite) SetupTest() { + s.app = app.Setup(s.T()) + s.ctx = s.app.BaseApp.NewContextLegacy(false, cmtproto.Header{Time: time.Now()}).WithBlockTime(time.Now()) + + s.nftKeeper = s.app.NFTKeeper + s.registryKeeper = s.app.RegistryKeeper + s.msgServer = keeper.NewMsgServer(s.registryKeeper) + + s.maintainer = genAddr() + s.nftOwner = genAddr() + + s.nftClass = nft.Class{Id: "participant-roles-test-nft-class"} + s.nftKeeper.SaveClass(s.ctx, s.nftClass) + + // Install the full participant registry class so every classed entry is governed by these policies. + _, err := s.msgServer.CreateRegistryClass(s.ctx, &types.MsgCreateRegistryClass{ + Signer: s.maintainer, + RegistryClassId: exampleClassID, + AssetClassId: s.nftClass.Id, + Maintainer: s.maintainer, + RoleAuthorizations: participantRoleAuthorizations(), + }) + s.Require().NoError(err) +} + +// registerWithRoles mints an NFT owned by s.nftOwner, registers it under the participant class, and seeds +// the given initial roles. It returns the registry key. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) registerWithRoles(id string, roles []types.RolesEntry) *types.RegistryKey { + n := nft.NFT{ClassId: s.nftClass.Id, Id: id} + ownerAddr, err := sdk.AccAddressFromBech32(s.nftOwner) + s.Require().NoError(err) + s.Require().NoError(s.nftKeeper.Mint(s.ctx, n, ownerAddr)) + + key := &types.RegistryKey{AssetClassId: s.nftClass.Id, NftId: id} + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, roles, exampleClassID)) + return key +} + +// propose opens a pending role change and returns the change id and whether it applied immediately. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) propose(key *types.RegistryKey, signer string, role types.RegistryRole, addrs []string) (string, bool) { + resp, err := s.msgServer.ProposeRoleChange(s.ctx, &types.MsgProposeRoleChange{ + Signer: signer, + Key: key, + RoleUpdates: []types.RoleUpdate{{Role: role, Addresses: addrs}}, + }) + s.Require().NoError(err) + return resp.ChangeId, resp.Applied +} + +// proposeErr attempts a proposal expected to be rejected because the proposer is not an eligible +// approver of the change, and returns the error. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) proposeErr(key *types.RegistryKey, signer string, role types.RegistryRole, addrs []string) error { + _, err := s.msgServer.ProposeRoleChange(s.ctx, &types.MsgProposeRoleChange{ + Signer: signer, + Key: key, + RoleUpdates: []types.RoleUpdate{{Role: role, Addresses: addrs}}, + }) + return err +} + +// approve records an approval for a pending change and returns whether it applied. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) approve(changeID, signer string) bool { + resp, err := s.msgServer.ApproveRoleChange(s.ctx, &types.MsgApproveRoleChange{ + Signer: signer, + ChangeId: changeID, + }) + s.Require().NoError(err) + return resp.Applied +} + +// roleAddresses returns the addresses currently assigned to role on the entry. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) roleAddresses(key *types.RegistryKey, role types.RegistryRole) []string { + entry, err := s.registryKeeper.GetRegistry(s.ctx, key) + s.Require().NoError(err) + s.Require().NotNil(entry) + for _, re := range entry.Roles { + if re.Role == role { + return re.Addresses + } + } + return nil +} + +// --- Consent-matrix tests ----------------------------------------------------------------------- + +// TestOriginator: an originator update requires the current originator (or NFT owner if unset) plus +// the incoming new originator. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) TestOriginator() { + role := types.RegistryRole_REGISTRY_ROLE_ORIGINATOR + currentOriginator := genAddr() + newOriginator := genAddr() + + s.Run("current + new originator approve", func() { + key := s.registerWithRoles("orig-happy", []types.RolesEntry{{Role: role, Addresses: []string{currentOriginator}}}) + + changeID, applied := s.propose(key, currentOriginator, role, []string{newOriginator}) + s.Require().False(applied, "current originator alone is not sufficient") + + applied = s.approve(changeID, newOriginator) + s.Require().True(applied, "current + new originator satisfy the policy") + s.Require().Equal([]string{newOriginator}, s.roleAddresses(key, role)) + }) + + s.Run("NFT owner acts as current originator when none is set", func() { + key := s.registerWithRoles("orig-nft-owner", nil) + + changeID, applied := s.propose(key, s.nftOwner, role, []string{newOriginator}) + s.Require().False(applied) + + applied = s.approve(changeID, newOriginator) + s.Require().True(applied) + s.Require().Equal([]string{newOriginator}, s.roleAddresses(key, role)) + }) + + s.Run("stranger cannot originate", func() { + key := s.registerWithRoles("orig-stranger", []types.RolesEntry{{Role: role, Addresses: []string{currentOriginator}}}) + + err := s.proposeErr(key, genAddr(), role, []string{newOriginator}) + s.Require().Error(err, "an ineligible proposer is rejected outright") + s.Require().Equal([]string{currentOriginator}, s.roleAddresses(key, role)) + }) +} + +// TestLienOwnerStandard: a standard lien owner transfer requires the current lien owner, the current +// Secured Party for Lien (if set), and the new lien owner. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) TestLienOwnerStandard() { + lienOwner := types.RegistryRole_REGISTRY_ROLE_LIEN_OWNER + securedParty := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN + + currentLienOwner := genAddr() + sp := genAddr() + newLienOwner := genAddr() + + baseRoles := func() []types.RolesEntry { + return []types.RolesEntry{ + {Role: lienOwner, Addresses: []string{currentLienOwner}}, + {Role: securedParty, Addresses: []string{sp}}, + } + } + + s.Run("current lien owner + secured party + new lien owner", func() { + key := s.registerWithRoles("lien-happy", baseRoles()) + + changeID, applied := s.propose(key, currentLienOwner, lienOwner, []string{newLienOwner}) + s.Require().False(applied) + + applied = s.approve(changeID, sp) + s.Require().False(applied, "still missing the new lien owner") + + applied = s.approve(changeID, newLienOwner) + s.Require().True(applied) + s.Require().Equal([]string{newLienOwner}, s.roleAddresses(key, lienOwner)) + }) + + s.Run("incomplete: missing secured party approval", func() { + key := s.registerWithRoles("lien-no-sp", baseRoles()) + + changeID, _ := s.propose(key, currentLienOwner, lienOwner, []string{newLienOwner}) + applied := s.approve(changeID, newLienOwner) + s.Require().False(applied, "secured party for lien must also approve") + s.Require().Equal([]string{currentLienOwner}, s.roleAddresses(key, lienOwner)) + }) +} + +// TestLienOwnerForeclosure: the Secured Party for Lien can unilaterally become the Lien Owner. A +// single proposal by the secured party (assigning the lien owner role to itself) satisfies the +// dedicated foreclosure authorization path. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) TestLienOwnerForeclosure() { + lienOwner := types.RegistryRole_REGISTRY_ROLE_LIEN_OWNER + securedParty := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN + + currentLienOwner := genAddr() + sp := genAddr() + + s.Run("secured party unilaterally forecloses into lien owner", func() { + key := s.registerWithRoles("lien-foreclose", []types.RolesEntry{ + {Role: lienOwner, Addresses: []string{currentLienOwner}}, + {Role: securedParty, Addresses: []string{sp}}, + }) + + _, applied := s.propose(key, sp, lienOwner, []string{sp}) + s.Require().True(applied, "foreclosure path: current secured party becomes the new lien owner") + s.Require().Equal([]string{sp}, s.roleAddresses(key, lienOwner)) + }) + + s.Run("stranger cannot foreclose", func() { + key := s.registerWithRoles("lien-foreclose-bad", []types.RolesEntry{ + {Role: lienOwner, Addresses: []string{currentLienOwner}}, + {Role: securedParty, Addresses: []string{sp}}, + }) + + stranger := genAddr() + _, applied := s.propose(key, stranger, lienOwner, []string{stranger}) + s.Require().False(applied) + s.Require().Equal([]string{currentLienOwner}, s.roleAddresses(key, lienOwner)) + }) +} + +// TestControllerForeclosure: the Secured Party for eNote can unilaterally become the Controller. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) TestControllerForeclosure() { + controller := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + securedParty := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE + + currentController := genAddr() + sp := genAddr() + + key := s.registerWithRoles("ctrl-foreclose", []types.RolesEntry{ + {Role: controller, Addresses: []string{currentController}}, + {Role: securedParty, Addresses: []string{sp}}, + }) + + _, applied := s.propose(key, sp, controller, []string{sp}) + s.Require().True(applied, "foreclosure path: current secured party for eNote becomes the controller") + s.Require().Equal([]string{sp}, s.roleAddresses(key, controller)) +} + +// TestServicer exercises a policy whose conditional requirement uses a role_priority selector +// (Secured Party for eNote, falling back to Pledgee). Granting a servicer requires the current +// controller, the conditional approver, and the new servicer. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) TestServicer() { + servicer := types.RegistryRole_REGISTRY_ROLE_SERVICER + controller := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + spEnote := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE + + currentController := genAddr() + sp := genAddr() + newServicer := genAddr() + + s.Run("controller + secured party for eNote + new servicer", func() { + key := s.registerWithRoles("svc-happy", []types.RolesEntry{ + {Role: controller, Addresses: []string{currentController}}, + {Role: spEnote, Addresses: []string{sp}}, + }) + + changeID, applied := s.propose(key, currentController, servicer, []string{newServicer}) + s.Require().False(applied) + + applied = s.approve(changeID, sp) + s.Require().False(applied, "still missing the new servicer") + + applied = s.approve(changeID, newServicer) + s.Require().True(applied) + s.Require().Equal([]string{newServicer}, s.roleAddresses(key, servicer)) + }) + + s.Run("incomplete: missing conditional secured-party approval", func() { + key := s.registerWithRoles("svc-no-sp", []types.RolesEntry{ + {Role: controller, Addresses: []string{currentController}}, + {Role: spEnote, Addresses: []string{sp}}, + }) + + changeID, _ := s.propose(key, currentController, servicer, []string{newServicer}) + applied := s.approve(changeID, newServicer) + s.Require().False(applied) + s.Require().Empty(s.roleAddresses(key, servicer)) + }) +} + +// TestAllParticipantPoliciesCoexist confirms the full set validates and persists together. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) TestAllParticipantPoliciesCoexist() { + got, err := s.registryKeeper.GetRegistryClass(s.ctx, exampleClassID) + s.Require().NoError(err) + s.Require().NotNil(got) + s.Require().Len(got.RoleAuthorizations, len(participantRoleAuthorizations())) +} + +// TestMalformedPolicyRejected verifies the deepened create-time validation rejects malformed +// authorization paths instead of letting them fail closed only at evaluation time. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) TestMalformedPolicyRejected() { + cases := []struct { + name string + auth types.RoleAuthorization + errPart string + }{ + { + name: "nft_role with NEW assignment", + auth: types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{ + Description: "bad", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raNft(types.NftRole_NFT_ROLE_NFT_OWNER, types.Assignment_ASSIGNMENT_NEW)), + }, + }}, + }, + errPart: "nft_role may only be used with a CURRENT*", + }, + { + name: "missing role selector", + auth: types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{ + Description: "bad", + Signatures: []*types.SignatureRequirement{ + {Type: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL, Roles: []*types.RoleAssignment{ + {Assignment: types.Assignment_ASSIGNMENT_CURRENT}, + }}, + }, + }}, + }, + errPart: "a role selector", + }, + { + name: "unspecified signature type", + auth: types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{ + Description: "bad", + Signatures: []*types.SignatureRequirement{ + {Roles: []*types.RoleAssignment{raRegistry(types.RegistryRole_REGISTRY_ROLE_CONTROLLER, types.Assignment_ASSIGNMENT_CURRENT)}}, + }, + }}, + }, + errPart: "type", + }, + { + name: "authorization path with no signature requirements", + auth: types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{Description: "empty"}}, + }, + errPart: "at least one signature requirement", + }, + } + + for _, tc := range cases { + s.Run(tc.name, func() { + _, err := s.msgServer.CreateRegistryClass(s.ctx, &types.MsgCreateRegistryClass{ + Signer: s.maintainer, + RegistryClassId: "bad-" + tc.name, + AssetClassId: s.nftClass.Id, + Maintainer: s.maintainer, + RoleAuthorizations: []types.RoleAuthorization{tc.auth}, + }) + s.Require().Error(err) + s.Require().ErrorContains(err, tc.errPart) + }) + } +} + +// TestExampleFixtureInSync verifies the committed example fixture proto-JSON decodes to exactly the +// participant policies built in code. Set REGEN_EXAMPLE_FIXTURE=1 to (re)generate the fixture file. +func (s *ParticipantRolePoliciesAcceptanceTestSuite) TestExampleFixtureInSync() { + path := filepath.Join("..", "spec", "examples", "example_registry_class.json") + + want := types.RegistryClass{ + RegistryClassId: exampleClassID, + AssetClassId: "loan.asset", + Maintainer: "pb1maintainerplaceholder0000000000000000000", + RoleAuthorizations: participantRoleAuthorizations(), + } + + if os.Getenv("REGEN_EXAMPLE_FIXTURE") == "1" { + bz, err := s.app.AppCodec().MarshalJSON(&want) + s.Require().NoError(err) + s.Require().NoError(os.WriteFile(path, append(bz, '\n'), 0o644)) + } + + bz, err := os.ReadFile(path) + s.Require().NoError(err, "example fixture missing; run with REGEN_EXAMPLE_FIXTURE=1 to generate") + + var got types.RegistryClass + s.Require().NoError(s.app.AppCodec().UnmarshalJSON(bz, &got)) + s.Require().Equal(want.RoleAuthorizations, got.RoleAuthorizations, + "example fixture is out of sync with code; run with REGEN_EXAMPLE_FIXTURE=1 to regenerate") +} + +// --- Participant policy builders (mirror requirements.md §"Participant Roles") --------------------- + +// participantRoleAuthorizations returns the full set of participant role policies. +func participantRoleAuthorizations() []types.RoleAuthorization { + return []types.RoleAuthorization{ + originatorPolicy(), + lienOwnerPolicy(), + controllerPolicy(), + securedPartyForLienPolicy(), + securedPartyForEnotePolicy(), + pledgeePolicy(), + servicerPolicy(), + subservicerPolicy(), + } +} + +func originatorPolicy() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_ORIGINATOR, + Authorizations: []*types.Authorization{{ + Description: "Assign originator (requires current and new originator approval)", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raPriority(types.Assignment_ASSIGNMENT_CURRENT, + rpRegistry(types.RegistryRole_REGISTRY_ROLE_ORIGINATOR), + rpNft(types.NftRole_NFT_ROLE_NFT_OWNER), + )), + sigReqAllIfSet(raRegistry(types.RegistryRole_REGISTRY_ROLE_ORIGINATOR, types.Assignment_ASSIGNMENT_NEW)), + }, + }}, + } +} + +func lienOwnerPolicy() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_LIEN_OWNER, + Authorizations: []*types.Authorization{ + { + Description: "Transfer requiring current lien owner approval", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raPriority(types.Assignment_ASSIGNMENT_CURRENT, + rpRegistry(types.RegistryRole_REGISTRY_ROLE_LIEN_OWNER), + rpNft(types.NftRole_NFT_ROLE_NFT_OWNER), + )), + sigReqAllIfSet( + raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_LIEN_OWNER, types.Assignment_ASSIGNMENT_NEW), + ), + }, + }, + { + Description: "Foreclosure: Secured Party for Lien can unilaterally become Lien Owner in case of default", + Signatures: []*types.SignatureRequirement{ + sigReqAll( + raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_LIEN_OWNER, types.Assignment_ASSIGNMENT_NEW), + ), + }, + }, + }, + } +} + +func controllerPolicy() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, + Authorizations: []*types.Authorization{ + { + Description: "Transfer requiring current controller approval", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raPriority(types.Assignment_ASSIGNMENT_CURRENT, + rpRegistry(types.RegistryRole_REGISTRY_ROLE_CONTROLLER), + rpNft(types.NftRole_NFT_ROLE_NFT_OWNER), + )), + sigReqAllIfSet( + raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_CONTROLLER, types.Assignment_ASSIGNMENT_NEW), + ), + }, + }, + { + Description: "Foreclosure: Secured Party for eNote can unilaterally become Controller in case of default", + Signatures: []*types.SignatureRequirement{ + sigReqAll( + raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_CONTROLLER, types.Assignment_ASSIGNMENT_NEW), + ), + }, + }, + }, + } +} + +func securedPartyForLienPolicy() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN, + Authorizations: []*types.Authorization{ + { + Description: "Update by current lien owner", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raPriority(types.Assignment_ASSIGNMENT_CURRENT, + rpRegistry(types.RegistryRole_REGISTRY_ROLE_LIEN_OWNER), + rpNft(types.NftRole_NFT_ROLE_NFT_OWNER), + )), + sigReqAllIfSet( + raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN, types.Assignment_ASSIGNMENT_NEW), + ), + }, + }, + { + Description: "Update by current secured party for lien", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN, types.Assignment_ASSIGNMENT_CURRENT)), + sigReqAllIfSet(raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN, types.Assignment_ASSIGNMENT_NEW)), + }, + }, + }, + } +} + +func securedPartyForEnotePolicy() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE, + Authorizations: []*types.Authorization{ + { + Description: "Update by current controller", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raPriority(types.Assignment_ASSIGNMENT_CURRENT, + rpRegistry(types.RegistryRole_REGISTRY_ROLE_CONTROLLER), + rpNft(types.NftRole_NFT_ROLE_NFT_OWNER), + )), + sigReqAllIfSet( + raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE, types.Assignment_ASSIGNMENT_NEW), + ), + }, + }, + { + Description: "Update by current secured party for eNote", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE, types.Assignment_ASSIGNMENT_CURRENT)), + sigReqAllIfSet(raRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE, types.Assignment_ASSIGNMENT_NEW)), + }, + }, + }, + } +} + +func pledgeePolicy() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_PLEDGEE, + Authorizations: []*types.Authorization{{ + Description: "Update pledgee with value owner approval", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raNft(types.NftRole_NFT_ROLE_NFT_OWNER, types.Assignment_ASSIGNMENT_CURRENT)), + sigReqAllIfSet( + raRegistry(types.RegistryRole_REGISTRY_ROLE_PLEDGEE, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_PLEDGEE, types.Assignment_ASSIGNMENT_NEW), + ), + }, + }}, + } +} + +func servicerPolicy() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{ + Description: "Update servicer with owner/controller approval", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raPriority(types.Assignment_ASSIGNMENT_CURRENT, + rpRegistry(types.RegistryRole_REGISTRY_ROLE_CONTROLLER), + rpNft(types.NftRole_NFT_ROLE_NFT_OWNER), + )), + sigReqAllIfSet( + raPriority(types.Assignment_ASSIGNMENT_CURRENT, + rpRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE), + rpRegistry(types.RegistryRole_REGISTRY_ROLE_PLEDGEE), + ), + raRegistry(types.RegistryRole_REGISTRY_ROLE_SERVICER, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_SERVICER, types.Assignment_ASSIGNMENT_NEW), + ), + }, + }}, + } +} + +func subservicerPolicy() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SUBSERVICER, + Authorizations: []*types.Authorization{{ + Description: "Update sub-servicer with owner/controller and servicer approval", + Signatures: []*types.SignatureRequirement{ + sigReqAll(raPriority(types.Assignment_ASSIGNMENT_CURRENT, + rpRegistry(types.RegistryRole_REGISTRY_ROLE_CONTROLLER), + rpNft(types.NftRole_NFT_ROLE_NFT_OWNER), + )), + sigReqAllIfSet( + raPriority(types.Assignment_ASSIGNMENT_CURRENT, + rpRegistry(types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE), + rpRegistry(types.RegistryRole_REGISTRY_ROLE_PLEDGEE), + ), + raRegistry(types.RegistryRole_REGISTRY_ROLE_SERVICER, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_SUBSERVICER, types.Assignment_ASSIGNMENT_CURRENT), + raRegistry(types.RegistryRole_REGISTRY_ROLE_SUBSERVICER, types.Assignment_ASSIGNMENT_NEW), + ), + }, + }}, + } +} + +// --- terse builder helpers ---------------------------------------------------------------------- + +func sigReqAll(roles ...*types.RoleAssignment) *types.SignatureRequirement { + return &types.SignatureRequirement{Type: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL, Roles: roles} +} + +func sigReqAllIfSet(roles ...*types.RoleAssignment) *types.SignatureRequirement { + return &types.SignatureRequirement{Type: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL_IF_SET, Roles: roles} +} + +func raRegistry(role types.RegistryRole, assignment types.Assignment) *types.RoleAssignment { + return &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RegistryRole{RegistryRole: role}, + Assignment: assignment, + } +} + +func raNft(nftRole types.NftRole, assignment types.Assignment) *types.RoleAssignment { + return &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_NftRole{NftRole: nftRole}, + Assignment: assignment, + } +} + +func raPriority(assignment types.Assignment, entries ...*types.RolePriorityEntry) *types.RoleAssignment { + return &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RolePriority{RolePriority: &types.RolePriority{Entries: entries}}, + Assignment: assignment, + } +} + +func rpRegistry(role types.RegistryRole) *types.RolePriorityEntry { + return &types.RolePriorityEntry{Role: &types.RolePriorityEntry_RegistryRole{RegistryRole: role}} +} + +func rpNft(nftRole types.NftRole) *types.RolePriorityEntry { + return &types.RolePriorityEntry{Role: &types.RolePriorityEntry_NftRole{NftRole: nftRole}} +} diff --git a/x/registry/keeper/pending.go b/x/registry/keeper/pending.go new file mode 100644 index 0000000000..6da9e88078 --- /dev/null +++ b/x/registry/keeper/pending.go @@ -0,0 +1,364 @@ +package keeper + +import ( + "context" + "errors" + "slices" + + "cosmossdk.io/collections" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + + "github.com/provenance-io/provenance/x/registry/types" +) + +// GetPendingRoleChange returns the pending role change for the given id, or nil if none exists. +func (k Keeper) GetPendingRoleChange(ctx context.Context, id string) (*types.PendingRoleChange, error) { + change, err := k.PendingRoleChanges.Get(ctx, id) + if err != nil { + if errors.Is(err, collections.ErrNotFound) { + return nil, nil + } + return nil, err + } + return &change, nil +} + +// SetPendingRoleChange stores a pending role change. +func (k Keeper) SetPendingRoleChange(ctx context.Context, change types.PendingRoleChange) error { + return k.PendingRoleChanges.Set(ctx, change.Id, change) +} + +// RemovePendingRoleChange deletes a pending role change by id. +func (k Keeper) RemovePendingRoleChange(ctx context.Context, id string) error { + return k.PendingRoleChanges.Remove(ctx, id) +} + +// GetPendingRoleChanges returns the pending role changes, optionally filtered to a single registry +// key. Results are paginated over the deterministic change-id keyspace. +func (k Keeper) GetPendingRoleChanges(ctx context.Context, pagination *query.PageRequest, key *types.RegistryKey) ([]types.PendingRoleChange, *query.PageResponse, error) { + ptrs, pageRes, err := query.CollectionFilteredPaginate(ctx, k.PendingRoleChanges, pagination, + func(_ string, change types.PendingRoleChange) (bool, error) { + if key == nil { + return true, nil + } + return change.Key != nil && + change.Key.AssetClassId == key.AssetClassId && + change.Key.NftId == key.NftId, nil + }, + func(_ string, change types.PendingRoleChange) (*types.PendingRoleChange, error) { + return &change, nil + }, + ) + if err != nil { + return nil, nil, err + } + + changes := make([]types.PendingRoleChange, len(ptrs)) + for i, p := range ptrs { + changes[i] = *p + } + return changes, pageRes, nil +} + +// EvaluateRoleChange performs a read-only authorization check of a desired-state role-change batch +// against the supplied approvers, returning the first affected role's authorization error (or nil if +// every affected role's policy is satisfied). It writes no state and is the basis for the +// ValidateRoleChange dry-run query. +func (k Keeper) EvaluateRoleChange(ctx context.Context, key *types.RegistryKey, roleUpdates []types.RoleUpdate, approvers []string) error { + entry, err := k.GetRegistry(ctx, key) + if err != nil { + return err + } + if entry == nil { + return types.NewErrCodeRegistryNotFound(key.String()) + } + + roleAuths, err := k.roleAuthorizationsForEntry(ctx, entry) + if err != nil { + return err + } + for _, update := range roleUpdates { + roleAuth, ok := roleAuths[update.Role] + if !ok { + // Legacy fallback: at least one approver must own the NFT. + owns := false + for _, a := range approvers { + if k.ValidateNFTOwner(ctx, &key.AssetClassId, &key.NftId, a) == nil { + owns = true + break + } + } + if !owns { + return types.NewErrCodeUnauthorized( + "role " + update.Role.ShortString() + " has no authorization policy; the NFT owner must approve", + ) + } + continue + } + + newAddrs := additions(entry.GetRoleAddrs(update.Role), update.Addresses) + if err := k.ValidateRoleChangeAuthorization(ctx, roleAuth, entry, newAddrs, approvers); err != nil { + return err + } + } + return nil +} + +// ProposeRoleChange opens (or re-uses) a pending role change for a batch of desired-state role +// updates and records the proposer's approval. If the accumulated approvals already satisfy every +// affected role's policy, the change is applied immediately. Returns the change id and whether it +// was applied. +func (k Keeper) ProposeRoleChange(ctx context.Context, proposer string, key *types.RegistryKey, roleUpdates []types.RoleUpdate) (string, bool, error) { + entry, err := k.GetRegistry(ctx, key) + if err != nil { + return "", false, err + } + if entry == nil { + return "", false, types.NewErrCodeRegistryNotFound(key.String()) + } + + id := types.NewPendingRoleChangeID(key, roleUpdates) + + change, err := k.GetPendingRoleChange(ctx, id) + if err != nil { + return "", false, err + } + if change == nil { + // Reject if there's already a different pending change for this key. Limiting to one + // pending change per NFT prevents conflicting proposals from accumulating; the existing + // change must be cancelled or applied first. Expired records are cleaned up eagerly here + // so they don't block new proposals indefinitely. + existing, _, err := k.GetPendingRoleChanges(ctx, nil, key) + if err != nil { + return "", false, err + } + blockTime := sdk.UnwrapSDKContext(ctx).BlockTime() + for _, ex := range existing { + if !ex.ExpiresAt.IsZero() && !blockTime.Before(ex.ExpiresAt) { + // Expired — remove it so it no longer blocks new proposals. + if rerr := k.RemovePendingRoleChange(ctx, ex.Id); rerr != nil { + return "", false, rerr + } + continue + } + return "", false, types.NewErrCodeInvalidField("role_updates", + "a pending role change already exists for this NFT; cancel or apply the existing change first") + } + + newChange := &types.PendingRoleChange{ + Id: id, + Key: key, + RoleUpdates: roleUpdates, + Proposer: proposer, + } + // Set expiry if the module params configure one. + if expiry := k.GetParams(ctx).PendingChangeExpiry; expiry > 0 { + newChange.ExpiresAt = sdk.UnwrapSDKContext(ctx).BlockTime().Add(expiry) + } + // Only open a new pending change when the proposer could actually contribute a valid + // approval to at least one affected role. This keeps state from growing via proposals + // opened by accounts that are not a required party for the change. + eligible, err := k.approverEligible(ctx, entry, newChange, proposer) + if err != nil { + return "", false, err + } + if !eligible { + return "", false, types.NewErrCodeUnauthorized( + "proposer " + proposer + " is not eligible to approve any affected role", + ) + } + change = newChange + k.EmitEvent(ctx, types.NewEventRoleChangeProposed(change)) + } else { + // Reusing an existing pending record (same change ID = same role updates, acting as a + // co-approval). Check expiry here too so that MsgProposeRoleChange cannot be used to + // bypass the expiry enforcement that applies to MsgApproveRoleChange. + if !change.ExpiresAt.IsZero() && !sdk.UnwrapSDKContext(ctx).BlockTime().Before(change.ExpiresAt) { + if rerr := k.RemovePendingRoleChange(ctx, change.Id); rerr != nil { + return "", false, rerr + } + return "", false, types.NewErrCodePendingChangeNotFound(change.Id + " (expired)") + } + } + + applied, err := k.recordApprovalAndMaybeApply(ctx, entry, change, proposer) + if err != nil { + return "", false, err + } + return id, applied, nil +} + +// ApproveRoleChange records an approval on an existing pending role change and applies it if the +// accumulated approvals now satisfy the role's policy. Returns whether the change was applied. +func (k Keeper) ApproveRoleChange(ctx context.Context, approver string, changeID string) (bool, error) { + change, err := k.GetPendingRoleChange(ctx, changeID) + if err != nil { + return false, err + } + if change == nil { + return false, types.NewErrCodePendingChangeNotFound(changeID) + } + + // Reject and clean up expired changes. + if !change.ExpiresAt.IsZero() && !sdk.UnwrapSDKContext(ctx).BlockTime().Before(change.ExpiresAt) { + if rerr := k.RemovePendingRoleChange(ctx, changeID); rerr != nil { + return false, rerr + } + return false, types.NewErrCodePendingChangeNotFound(changeID + " (expired)") + } + + entry, err := k.GetRegistry(ctx, change.Key) + if err != nil { + return false, err + } + if entry == nil { + // The registry was removed out from under the pending change; clean it up. + if rerr := k.RemovePendingRoleChange(ctx, changeID); rerr != nil { + return false, rerr + } + return false, types.NewErrCodeRegistryNotFound(change.Key.String()) + } + + return k.recordApprovalAndMaybeApply(ctx, entry, change, approver) +} + +// recordApprovalAndMaybeApply adds approver to the change's approval set, evaluates the role's +// authorization policy against the accumulated approvals, and either applies and removes the +// change (returns true) or persists the updated change (returns false). +// +// Approvals from addresses that are not eligible under any affected role's policy are silently +// ignored: they can never contribute to satisfying the change, so recording them would only let a +// third party grow the approval set without bound (state bloat / DoS). +func (k Keeper) recordApprovalAndMaybeApply(ctx context.Context, entry *types.RegistryEntry, change *types.PendingRoleChange, approver string) (bool, error) { + eligible, err := k.approverEligible(ctx, entry, change, approver) + if err != nil { + return false, err + } + if eligible && !slices.Contains(change.Approvals, approver) { + change.Approvals = append(change.Approvals, approver) + k.EmitEvent(ctx, types.NewEventRoleChangeApproved(change.Id, approver)) + } + + satisfied, err := k.pendingChangeSatisfied(ctx, entry, change) + if err != nil { + return false, err + } + if !satisfied { + if err := k.SetPendingRoleChange(ctx, *change); err != nil { + return false, err + } + return false, nil + } + + if err := k.applyPendingChange(ctx, entry, change); err != nil { + return false, err + } + if err := k.RemovePendingRoleChange(ctx, change.Id); err != nil { + return false, err + } + k.EmitEvent(ctx, types.NewEventRoleChangeApplied(change)) + return true, nil +} + +// approverEligible reports whether approver could contribute to satisfying any of the change's +// role-update gates: for a policy-governed role they must be one of the policy's referenced +// addresses, and for a non-policy role they must own the NFT (the legacy fallback). +func (k Keeper) approverEligible(ctx context.Context, entry *types.RegistryEntry, change *types.PendingRoleChange, approver string) (bool, error) { + roleAuths, err := k.roleAuthorizationsForEntry(ctx, entry) + if err != nil { + return false, err + } + for _, update := range change.RoleUpdates { + roleAuth, ok := roleAuths[update.Role] + if !ok { + // Non-policy role: only the NFT owner can satisfy the fallback. + if k.ValidateNFTOwner(ctx, &change.Key.AssetClassId, &change.Key.NftId, approver) == nil { + return true, nil + } + continue + } + + newAddrs := additions(entry.GetRoleAddrs(update.Role), update.Addresses) + if k.CollectPolicyApprovers(ctx, roleAuth, entry, newAddrs)[approver] { + return true, nil + } + } + return false, nil +} + +// pendingChangeSatisfied reports whether the accumulated approvals satisfy every affected role's +// authorization policy. A role with no policy falls back to NFT ownership: at least one approver +// must own the NFT. The change applies only when all role updates are satisfied (atomic gate). +func (k Keeper) pendingChangeSatisfied(ctx context.Context, entry *types.RegistryEntry, change *types.PendingRoleChange) (bool, error) { + roleAuths, err := k.roleAuthorizationsForEntry(ctx, entry) + if err != nil { + return false, err + } + for _, update := range change.RoleUpdates { + roleAuth, ok := roleAuths[update.Role] + if !ok { + // Legacy fallback: at least one approver must own the NFT. + if !k.anyApproverOwnsNFT(ctx, change) { + return false, nil + } + continue + } + + // Only addresses being newly added to the role are relevant for ASSIGNMENT_NEW checks. + newAddrs := additions(entry.GetRoleAddrs(update.Role), update.Addresses) + if k.ValidateRoleChangeAuthorization(ctx, roleAuth, entry, newAddrs, change.Approvals) != nil { + return false, nil + } + } + return true, nil +} + +// anyApproverOwnsNFT reports whether any accumulated approver owns the change's NFT. +func (k Keeper) anyApproverOwnsNFT(ctx context.Context, change *types.PendingRoleChange) bool { + for _, approver := range change.Approvals { + if k.ValidateNFTOwner(ctx, &change.Key.AssetClassId, &change.Key.NftId, approver) == nil { + return true + } + } + return false +} + +// additions returns the addresses in desired that are not already present in current. +func additions(current, desired []string) []string { + if len(current) == 0 { + return desired + } + have := make(map[string]bool, len(current)) + for _, a := range current { + have[a] = true + } + var added []string + for _, a := range desired { + if !have[a] { + added = append(added, a) + } + } + return added +} + +// applyPendingChange applies the batch of role updates as a single atomic desired-state set and +// emits an EventRoleUpdated per role using the accumulated approvals as the authorizing signer set. +// before is the pre-mutation entry, captured for previous addresses and signer resolution. +func (k Keeper) applyPendingChange(ctx context.Context, before *types.RegistryEntry, change *types.PendingRoleChange) error { + if err := k.SetRoles(ctx, change.Key, change.RoleUpdates); err != nil { + return err + } + for _, update := range change.RoleUpdates { + newAddrs := additions(before.GetRoleAddrs(update.Role), update.Addresses) + signers, err := k.roleChangeSigners(ctx, before, update.Role, newAddrs, change.Approvals) + if err != nil { + return err + } + if err := k.emitRoleUpdated(ctx, before, update.Role, signers); err != nil { + return err + } + } + return nil +} diff --git a/x/registry/keeper/pending_query_test.go b/x/registry/keeper/pending_query_test.go new file mode 100644 index 0000000000..4a9e4fa8d8 --- /dev/null +++ b/x/registry/keeper/pending_query_test.go @@ -0,0 +1,146 @@ +package keeper_test + +import ( + "github.com/cosmos/cosmos-sdk/types/query" + + "github.com/provenance-io/provenance/testutil/assertions" + "github.com/provenance-io/provenance/x/registry/keeper" + "github.com/provenance-io/provenance/x/registry/types" +) + +// newPendingChange builds and stores a pending role change for the given key and addresses. +func (s *KeeperTestSuite) newPendingChange(key *types.RegistryKey, addresses []string) types.PendingRoleChange { + roleUpdates := []types.RoleUpdate{{ + Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, + Addresses: addresses, + }} + change := types.PendingRoleChange{ + Id: types.NewPendingRoleChangeID(key, roleUpdates), + Key: key, + RoleUpdates: roleUpdates, + Proposer: s.user1, + Approvals: []string{s.user1}, + } + s.Require().NoError(s.app.RegistryKeeper.SetPendingRoleChange(s.ctx, change)) + return change +} + +func (s *KeeperTestSuite) TestQueryPendingRoleChange() { + key := &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} + change := s.newPendingChange(key, []string{s.user2}) + + queryServer := keeper.NewQueryServer(s.app.RegistryKeeper) + + tests := []struct { + name string + req *types.QueryPendingRoleChangeRequest + expErr string + expID string + }{ + { + name: "nil request", + req: nil, + expErr: "empty request", + }, + { + name: "empty id", + req: &types.QueryPendingRoleChangeRequest{Id: ""}, + expErr: "id cannot be empty", + }, + { + name: "not found", + req: &types.QueryPendingRoleChangeRequest{Id: "does-not-exist"}, + expErr: "pending role change", + }, + { + name: "found", + req: &types.QueryPendingRoleChangeRequest{Id: change.Id}, + expID: change.Id, + }, + } + + for _, tc := range tests { + s.Run(tc.name, func() { + resp, err := queryServer.PendingRoleChange(s.ctx, tc.req) + if tc.expErr != "" { + assertions.AssertErrorContents(s.T(), err, []string{tc.expErr}, "PendingRoleChange") + return + } + s.Require().NoError(err) + s.Require().NotNil(resp) + s.Require().Equal(tc.expID, resp.PendingRoleChange.Id) + }) + } +} + +func (s *KeeperTestSuite) TestQueryPendingRoleChanges() { + key1 := &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} + key2 := &types.RegistryKey{AssetClassId: "other-class", NftId: "other-nft"} + + c1 := s.newPendingChange(key1, []string{s.user2}) + c2 := s.newPendingChange(key2, []string{s.user2}) + + queryServer := keeper.NewQueryServer(s.app.RegistryKeeper) + + s.Run("nil request", func() { + _, err := queryServer.PendingRoleChanges(s.ctx, nil) + assertions.AssertErrorContents(s.T(), err, []string{"empty request"}, "PendingRoleChanges") + }) + + s.Run("all changes", func() { + resp, err := queryServer.PendingRoleChanges(s.ctx, &types.QueryPendingRoleChangesRequest{}) + s.Require().NoError(err) + s.Require().Len(resp.PendingRoleChanges, 2) + ids := []string{resp.PendingRoleChanges[0].Id, resp.PendingRoleChanges[1].Id} + s.Require().ElementsMatch([]string{c1.Id, c2.Id}, ids) + }) + + s.Run("filter by key", func() { + resp, err := queryServer.PendingRoleChanges(s.ctx, &types.QueryPendingRoleChangesRequest{Key: key1}) + s.Require().NoError(err) + s.Require().Len(resp.PendingRoleChanges, 1) + s.Require().Equal(c1.Id, resp.PendingRoleChanges[0].Id) + }) + + s.Run("filter by key with no matches", func() { + empty := &types.RegistryKey{AssetClassId: "nope", NftId: "nope"} + resp, err := queryServer.PendingRoleChanges(s.ctx, &types.QueryPendingRoleChangesRequest{Key: empty}) + s.Require().NoError(err) + s.Require().Empty(resp.PendingRoleChanges) + }) + + s.Run("paginated", func() { + resp, err := queryServer.PendingRoleChanges(s.ctx, &types.QueryPendingRoleChangesRequest{ + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + }) + s.Require().NoError(err) + s.Require().Len(resp.PendingRoleChanges, 1) + s.Require().NotNil(resp.Pagination) + s.Require().Equal(uint64(2), resp.Pagination.Total) + }) +} + +func (s *KeeperTestSuite) TestPendingRoleChangeGenesisRoundTrip() { + key := &types.RegistryKey{AssetClassId: s.validNFTClass.Id, NftId: s.validNFT.Id} + change := s.newPendingChange(key, []string{s.user2}) + + genesis := s.app.RegistryKeeper.ExportGenesis(s.ctx) + s.Require().Len(genesis.PendingRoleChanges, 1) + s.Require().Equal(change.Id, genesis.PendingRoleChanges[0].Id) + + // Clear and re-import. + s.Require().NoError(s.app.RegistryKeeper.RemovePendingRoleChange(s.ctx, change.Id)) + got, err := s.app.RegistryKeeper.GetPendingRoleChange(s.ctx, change.Id) + s.Require().NoError(err) + s.Require().Nil(got) + + s.Require().NotPanics(func() { + s.app.RegistryKeeper.InitGenesis(s.ctx, genesis) + }) + + got, err = s.app.RegistryKeeper.GetPendingRoleChange(s.ctx, change.Id) + s.Require().NoError(err) + s.Require().NotNil(got) + s.Require().Equal(change.Approvals, got.Approvals) + s.Require().Equal(change.RoleUpdates, got.RoleUpdates) +} diff --git a/x/registry/keeper/query_server.go b/x/registry/keeper/query_server.go index 6c1988776f..d2da8d2d28 100644 --- a/x/registry/keeper/query_server.go +++ b/x/registry/keeper/query_server.go @@ -91,3 +91,114 @@ func (qs QueryServer) HasRole(ctx context.Context, req *types.QueryHasRoleReques return &types.QueryHasRoleResponse{HasRole: hasRole}, nil } + +// PendingRoleChange returns a single pending role change by its id. +func (qs QueryServer) PendingRoleChange(ctx context.Context, req *types.QueryPendingRoleChangeRequest) (*types.QueryPendingRoleChangeResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + if err := req.Validate(); err != nil { + return nil, err + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + change, err := qs.keeper.GetPendingRoleChange(sdkCtx, req.Id) + if err != nil { + return nil, err + } + if change == nil { + return nil, types.NewErrCodePendingChangeNotFound(req.Id) + } + + return &types.QueryPendingRoleChangeResponse{PendingRoleChange: *change}, nil +} + +// PendingRoleChanges returns the pending role changes, optionally filtered by registry key. +func (qs QueryServer) PendingRoleChanges(ctx context.Context, req *types.QueryPendingRoleChangesRequest) (*types.QueryPendingRoleChangesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + if err := req.Validate(); err != nil { + return nil, err + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + changes, pageRes, err := qs.keeper.GetPendingRoleChanges(sdkCtx, req.Pagination, req.Key) + if err != nil { + return nil, err + } + + return &types.QueryPendingRoleChangesResponse{PendingRoleChanges: changes, Pagination: pageRes}, nil +} + +// RegistryClass returns a single registry class (including its authorization policy) by id. +func (qs QueryServer) RegistryClass(ctx context.Context, req *types.QueryRegistryClassRequest) (*types.QueryRegistryClassResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + if err := req.Validate(); err != nil { + return nil, err + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + class, err := qs.keeper.GetRegistryClass(sdkCtx, req.RegistryClassId) + if err != nil { + return nil, err + } + if class == nil { + return nil, types.NewErrCodeRegistryClassNotFound(req.RegistryClassId) + } + + return &types.QueryRegistryClassResponse{RegistryClass: *class}, nil +} + +// RegistryClasses returns all registry classes, paginated. +func (qs QueryServer) RegistryClasses(ctx context.Context, req *types.QueryRegistryClassesRequest) (*types.QueryRegistryClassesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + if err := req.Validate(); err != nil { + return nil, err + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + classes, pageRes, err := qs.keeper.GetRegistryClasses(sdkCtx, req.Pagination) + if err != nil { + return nil, err + } + + return &types.QueryRegistryClassesResponse{RegistryClasses: classes, Pagination: pageRes}, nil +} + +// Params returns the registry module parameters. +func (qs QueryServer) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + return &types.QueryParamsResponse{Params: qs.keeper.GetParams(sdkCtx)}, nil +} + +// ValidateRoleChange performs a read-only dry-run of a role-change batch, reporting whether the +// supplied approvers would satisfy every affected role's authorization policy. It writes no state. +func (qs QueryServer) ValidateRoleChange(ctx context.Context, req *types.QueryValidateRoleChangeRequest) (*types.QueryValidateRoleChangeResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + if err := req.Validate(); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + if err := qs.keeper.EvaluateRoleChange(sdkCtx, req.Key, req.RoleUpdates, req.Approvers); err != nil { + return &types.QueryValidateRoleChangeResponse{Error: err.Error(), Authorized: false}, nil + } + return &types.QueryValidateRoleChangeResponse{Error: "", Authorized: true}, nil +} diff --git a/x/registry/keeper/query_server_test.go b/x/registry/keeper/query_server_test.go index a614a0be40..01b095279a 100644 --- a/x/registry/keeper/query_server_test.go +++ b/x/registry/keeper/query_server_test.go @@ -20,7 +20,7 @@ func (s *KeeperTestSuite) TestQueryGetRegistry() { Addresses: []string{s.user1}, }, } - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles, "") s.Require().NoError(err) queryServer := keeper.NewQueryServer(s.app.RegistryKeeper) @@ -127,7 +127,7 @@ func (s *KeeperTestSuite) TestQueryGetRegistries() { } for _, key := range keys { - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles, "") s.Require().NoError(err) } @@ -248,7 +248,7 @@ func (s *KeeperTestSuite) TestQueryHasRole() { Addresses: []string{s.user1, s.user2}, }, } - err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles) + err := s.app.RegistryKeeper.CreateRegistry(s.ctx, key, roles, "") s.Require().NoError(err) queryServer := keeper.NewQueryServer(s.app.RegistryKeeper) @@ -371,3 +371,179 @@ func (s *KeeperTestSuite) TestQueryHasRole() { }) } } + +// createQueryTestClass stores a minimal, valid registry class for query-server tests and returns it. +func (s *KeeperTestSuite) createQueryTestClass(classID string) types.RegistryClass { + class := types.RegistryClass{ + RegistryClassId: classID, + AssetClassId: s.validNFTClass.Id, + Maintainer: s.user1, + RoleAuthorizations: []types.RoleAuthorization{ + singleSigPolicy(&types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RegistryRole{RegistryRole: types.RegistryRole_REGISTRY_ROLE_CONTROLLER}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + }), + }, + } + s.Require().NoError(s.app.RegistryKeeper.CreateRegistryClass(s.ctx, class)) + return class +} + +func (s *KeeperTestSuite) TestQueryRegistryClass() { + stored := s.createQueryTestClass("query-class-1") + queryServer := keeper.NewQueryServer(s.app.RegistryKeeper) + + tests := []struct { + name string + req *types.QueryRegistryClassRequest + expErr string + }{ + { + name: "nil request", + req: nil, + expErr: "empty request", + }, + { + name: "empty registry_class_id", + req: &types.QueryRegistryClassRequest{RegistryClassId: ""}, + expErr: "registry_class_id cannot be empty", + }, + { + name: "malformed registry_class_id", + req: &types.QueryRegistryClassRequest{RegistryClassId: "bad id!"}, + expErr: "alphanumeric", + }, + { + name: "class does not exist", + req: &types.QueryRegistryClassRequest{RegistryClassId: "nonexistent"}, + expErr: "registry class", + }, + { + name: "class exists", + req: &types.QueryRegistryClassRequest{RegistryClassId: stored.RegistryClassId}, + }, + } + + for _, tc := range tests { + s.Run(tc.name, func() { + resp, err := queryServer.RegistryClass(s.ctx, tc.req) + if tc.expErr != "" { + assertions.RequireErrorContents(s.T(), err, []string{tc.expErr}) + s.Require().Nil(resp) + } else { + assertions.RequireErrorContents(s.T(), err, nil) + s.Require().NotNil(resp) + s.Require().Equal(stored.RegistryClassId, resp.RegistryClass.RegistryClassId) + s.Require().Equal(stored.Maintainer, resp.RegistryClass.Maintainer) + s.Require().Len(resp.RegistryClass.RoleAuthorizations, 1) + } + }) + } +} + +func (s *KeeperTestSuite) TestQueryRegistryClasses() { + s.createQueryTestClass("query-classes-a") + s.createQueryTestClass("query-classes-b") + s.createQueryTestClass("query-classes-c") + queryServer := keeper.NewQueryServer(s.app.RegistryKeeper) + + tests := []struct { + name string + req *types.QueryRegistryClassesRequest + expErr string + expCount int + }{ + { + name: "nil request", + req: nil, + expErr: "empty request", + }, + { + name: "all classes", + req: &types.QueryRegistryClassesRequest{}, + expCount: 3, + }, + { + name: "pagination limit", + req: &types.QueryRegistryClassesRequest{ + Pagination: &query.PageRequest{Limit: 2, CountTotal: true}, + }, + expCount: 2, + }, + { + name: "pagination offset", + req: &types.QueryRegistryClassesRequest{ + Pagination: &query.PageRequest{Offset: 2, Limit: 2}, + }, + expCount: 1, + }, + } + + for _, tc := range tests { + s.Run(tc.name, func() { + resp, err := queryServer.RegistryClasses(s.ctx, tc.req) + if tc.expErr != "" { + assertions.RequireErrorContents(s.T(), err, []string{tc.expErr}) + s.Require().Nil(resp) + } else { + assertions.RequireErrorContents(s.T(), err, nil) + s.Require().NotNil(resp) + s.Require().Len(resp.RegistryClasses, tc.expCount) + if tc.req.Pagination != nil && tc.req.Pagination.CountTotal { + s.Require().NotNil(resp.Pagination) + } + } + }) + } +} + +func (s *KeeperTestSuite) TestQueryParams() { + queryServer := keeper.NewQueryServer(s.app.RegistryKeeper) + + s.Run("nil request", func() { + resp, err := queryServer.Params(s.ctx, nil) + assertions.RequireErrorContents(s.T(), err, []string{"empty request"}) + s.Require().Nil(resp) + }) + + s.Run("default params", func() { + resp, err := queryServer.Params(s.ctx, &types.QueryParamsRequest{}) + assertions.RequireErrorContents(s.T(), err, nil) + s.Require().NotNil(resp) + s.Require().Empty(resp.Params.RoleAuthorizations) + }) + + s.Run("reflects set params", func() { + s.Require().NoError(s.app.RegistryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + })) + resp, err := queryServer.Params(s.ctx, &types.QueryParamsRequest{}) + assertions.RequireErrorContents(s.T(), err, nil) + s.Require().NotNil(resp) + s.Require().Len(resp.Params.RoleAuthorizations, 1) + s.Require().Equal(types.RegistryRole_REGISTRY_ROLE_CONTROLLER, resp.Params.RoleAuthorizations[0].Role) + }) +} + +// TestKeeperRegistryClassLifecycle exercises the keeper-level class store accessors directly: +// HasRegistryClass before/after creation and GetRegistryClasses listing. +func (s *KeeperTestSuite) TestKeeperRegistryClassLifecycle() { + has, err := s.app.RegistryKeeper.HasRegistryClass(s.ctx, "lifecycle-class") + s.Require().NoError(err) + s.Require().False(has) + + got, err := s.app.RegistryKeeper.GetRegistryClass(s.ctx, "lifecycle-class") + s.Require().NoError(err) + s.Require().Nil(got) + + s.createQueryTestClass("lifecycle-class") + + has, err = s.app.RegistryKeeper.HasRegistryClass(s.ctx, "lifecycle-class") + s.Require().NoError(err) + s.Require().True(has) + + classes, _, err := s.app.RegistryKeeper.GetRegistryClasses(s.ctx, nil) + s.Require().NoError(err) + s.Require().Len(classes, 1) + s.Require().Equal("lifecycle-class", classes[0].RegistryClassId) +} diff --git a/x/registry/keeper/registry_class_acceptance_test.go b/x/registry/keeper/registry_class_acceptance_test.go new file mode 100644 index 0000000000..fc03448af1 --- /dev/null +++ b/x/registry/keeper/registry_class_acceptance_test.go @@ -0,0 +1,328 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "cosmossdk.io/x/nft" + nftkeeper "cosmossdk.io/x/nft/keeper" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/provenance-io/provenance/app" + "github.com/provenance-io/provenance/x/registry/keeper" + "github.com/provenance-io/provenance/x/registry/types" +) + +// RegistryClassAcceptanceTestSuite covers Phase C1: registry classes provide maintainer-managed, +// asset-class-level authorization configuration that overrides the module's static default policy +// via two-tier resolution (class policy -> static default / NFT-owner fallback). +type RegistryClassAcceptanceTestSuite struct { + suite.Suite + + app *app.App + ctx sdk.Context + + registryKeeper keeper.Keeper + nftKeeper nftkeeper.Keeper + msgServer types.MsgServer + + nftClass nft.Class + + nftOwner string + maintainer string + controller string + stranger string + grantee string +} + +func TestRegistryClassAcceptanceTestSuite(t *testing.T) { + suite.Run(t, new(RegistryClassAcceptanceTestSuite)) +} + +func (s *RegistryClassAcceptanceTestSuite) SetupTest() { + s.app = app.Setup(s.T()) + s.ctx = s.app.BaseApp.NewContextLegacy(false, cmtproto.Header{Time: time.Now()}).WithBlockTime(time.Now()) + + s.nftKeeper = s.app.NFTKeeper + s.registryKeeper = s.app.RegistryKeeper + s.msgServer = keeper.NewMsgServer(s.registryKeeper) + + s.nftOwner = genAddr() + s.maintainer = genAddr() + s.controller = genAddr() + s.stranger = genAddr() + s.grantee = genAddr() + + s.nftClass = nft.Class{Id: "registry-class-test-nft-class"} + s.nftKeeper.SaveClass(s.ctx, s.nftClass) +} + +// mintNFT mints an NFT owned by s.nftOwner and returns its registry key. +func (s *RegistryClassAcceptanceTestSuite) mintNFT(id string) *types.RegistryKey { + n := nft.NFT{ClassId: s.nftClass.Id, Id: id} + ownerAddr, err := sdk.AccAddressFromBech32(s.nftOwner) + s.Require().NoError(err) + s.Require().NoError(s.nftKeeper.Mint(s.ctx, n, ownerAddr)) + return &types.RegistryKey{AssetClassId: s.nftClass.Id, NftId: id} +} + +// servicerRoleAuthorization builds a class policy for the SERVICER role that is satisfied by the +// current CONTROLLER's signature alone. This deviates from the static default (which only governs +// CONTROLLER and would otherwise fall back to NFT-owner authorization for SERVICER), letting us +// observe two-tier resolution. +func servicerRoleAuthorization() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{ + { + Description: "current controller may manage servicers", + Signatures: []*types.SignatureRequirement{ + { + Type: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL, + Roles: []*types.RoleAssignment{ + { + RoleSelector: &types.RoleAssignment_RegistryRole{ + RegistryRole: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, + }, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + }, + }, + }, + }, + }, + }, + } +} + +func (s *RegistryClassAcceptanceTestSuite) createClass(classID string, auths []types.RoleAuthorization) { + _, err := s.msgServer.CreateRegistryClass(s.ctx, &types.MsgCreateRegistryClass{ + Signer: s.maintainer, + RegistryClassId: classID, + AssetClassId: s.nftClass.Id, + Maintainer: s.maintainer, + RoleAuthorizations: auths, + }) + s.Require().NoError(err) +} + +// TestCreateRegistryClass exercises class creation success and failure paths. +func (s *RegistryClassAcceptanceTestSuite) TestCreateRegistryClass() { + s.Run("success: signer is maintainer", func() { + _, err := s.msgServer.CreateRegistryClass(s.ctx, &types.MsgCreateRegistryClass{ + Signer: s.maintainer, + RegistryClassId: "class-create-ok", + AssetClassId: s.nftClass.Id, + Maintainer: s.maintainer, + }) + s.Require().NoError(err) + + got, err := s.registryKeeper.GetRegistryClass(s.ctx, "class-create-ok") + s.Require().NoError(err) + s.Require().NotNil(got) + s.Require().Equal(s.maintainer, got.Maintainer) + s.Require().Equal(s.nftClass.Id, got.AssetClassId) + }) + + s.Run("reject: signer is not maintainer (ValidateBasic)", func() { + msg := &types.MsgCreateRegistryClass{ + Signer: s.stranger, + RegistryClassId: "class-bad-signer", + AssetClassId: s.nftClass.Id, + Maintainer: s.maintainer, + } + err := msg.ValidateBasic() + s.Require().Error(err) + s.Require().ErrorContains(err, "signer") + }) + + s.Run("reject: duplicate registry class id", func() { + s.createClass("class-dup", nil) + _, err := s.msgServer.CreateRegistryClass(s.ctx, &types.MsgCreateRegistryClass{ + Signer: s.maintainer, + RegistryClassId: "class-dup", + AssetClassId: s.nftClass.Id, + Maintainer: s.maintainer, + }) + s.Require().Error(err) + s.Require().ErrorContains(err, "class-dup") + }) +} + +// TestUpdateRegistryClassRoleAuthorization exercises the maintainer-only update path. +func (s *RegistryClassAcceptanceTestSuite) TestUpdateRegistryClassRoleAuthorization() { + s.createClass("class-update", nil) + + s.Run("success: maintainer updates authorizations", func() { + _, err := s.msgServer.UpdateRegistryClassRoleAuthorization(s.ctx, &types.MsgUpdateRegistryClassRoleAuthorization{ + Signer: s.maintainer, + RegistryClassId: "class-update", + RoleAuthorizations: []types.RoleAuthorization{servicerRoleAuthorization()}, + }) + s.Require().NoError(err) + + got, err := s.registryKeeper.GetRegistryClass(s.ctx, "class-update") + s.Require().NoError(err) + s.Require().NotNil(got) + s.Require().Len(got.RoleAuthorizations, 1) + s.Require().Equal(types.RegistryRole_REGISTRY_ROLE_SERVICER, got.RoleAuthorizations[0].Role) + }) + + s.Run("reject: non-maintainer cannot update", func() { + _, err := s.msgServer.UpdateRegistryClassRoleAuthorization(s.ctx, &types.MsgUpdateRegistryClassRoleAuthorization{ + Signer: s.stranger, + RegistryClassId: "class-update", + }) + s.Require().Error(err) + s.Require().ErrorContains(err, "maintainer") + }) + + s.Run("reject: unknown registry class", func() { + _, err := s.msgServer.UpdateRegistryClassRoleAuthorization(s.ctx, &types.MsgUpdateRegistryClassRoleAuthorization{ + Signer: s.maintainer, + RegistryClassId: "does-not-exist", + }) + s.Require().Error(err) + s.Require().ErrorContains(err, "does-not-exist") + }) +} + +// TestRegisterNFTWithRegistryClass verifies that registering against a class requires the class to +// exist and persists the reference on the entry. +func (s *RegistryClassAcceptanceTestSuite) TestRegisterNFTWithRegistryClass() { + s.createClass("class-register", []types.RoleAuthorization{servicerRoleAuthorization()}) + + s.Run("reject: unknown registry class", func() { + key := s.mintNFT("nft-missing-class") + _, err := s.msgServer.RegisterNFT(s.ctx, &types.MsgRegisterNFT{ + Signer: s.nftOwner, + Key: key, + RegistryClassId: "no-such-class", + }) + s.Require().Error(err) + s.Require().ErrorContains(err, "no-such-class") + }) + + s.Run("reject: registry class for a different asset class", func() { + _, err := s.msgServer.CreateRegistryClass(s.ctx, &types.MsgCreateRegistryClass{ + Signer: s.maintainer, + RegistryClassId: "class-other-asset", + AssetClassId: "some-other-asset-class", + Maintainer: s.maintainer, + RoleAuthorizations: []types.RoleAuthorization{servicerRoleAuthorization()}, + }) + s.Require().NoError(err) + + key := s.mintNFT("nft-mismatched-class") + _, err = s.msgServer.RegisterNFT(s.ctx, &types.MsgRegisterNFT{ + Signer: s.nftOwner, + Key: key, + RegistryClassId: "class-other-asset", + }) + s.Require().Error(err) + s.Require().ErrorContains(err, "is for asset class \"some-other-asset-class\"") + }) + + s.Run("success: entry stores registry class id", func() { + key := s.mintNFT("nft-with-class") + _, err := s.msgServer.RegisterNFT(s.ctx, &types.MsgRegisterNFT{ + Signer: s.nftOwner, + Key: key, + RegistryClassId: "class-register", + }) + s.Require().NoError(err) + + entry, err := s.registryKeeper.GetRegistry(s.ctx, key) + s.Require().NoError(err) + s.Require().NotNil(entry) + s.Require().Equal("class-register", entry.RegistryClassId) + }) +} + +// TestTwoTierResolution proves that an entry referencing a class is governed by the class policy, +// while an otherwise-identical entry with no class falls back to the static default (NFT-owner) for +// the same role. +func (s *RegistryClassAcceptanceTestSuite) TestTwoTierResolution() { + s.createClass("class-servicer", []types.RoleAuthorization{servicerRoleAuthorization()}) + + roles := []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.controller}}, + } + + s.Run("class policy: current controller may grant SERVICER", func() { + key := s.mintNFT("nft-classed") + _, err := s.msgServer.RegisterNFT(s.ctx, &types.MsgRegisterNFT{ + Signer: s.nftOwner, + Key: key, + Roles: roles, + RegistryClassId: "class-servicer", + }) + s.Require().NoError(err) + + // The controller (not the NFT owner) satisfies the class policy for SERVICER. + _, err = s.msgServer.GrantRole(s.ctx, &types.MsgGrantRole{ + Signer: s.controller, + Key: key, + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{s.grantee}, + }) + s.Require().NoError(err) + + hasRole, err := s.registryKeeper.HasRole(s.ctx, key, types.RegistryRole_REGISTRY_ROLE_SERVICER, s.grantee) + s.Require().NoError(err) + s.Require().True(hasRole) + }) + + s.Run("legacy fallback: controller cannot grant SERVICER without a class", func() { + key := s.mintNFT("nft-unclassed") + _, err := s.msgServer.RegisterNFT(s.ctx, &types.MsgRegisterNFT{ + Signer: s.nftOwner, + Key: key, + Roles: roles, + }) + s.Require().NoError(err) + + // No class -> SERVICER is not in the static map -> NFT-owner authorization is required. + _, err = s.msgServer.GrantRole(s.ctx, &types.MsgGrantRole{ + Signer: s.controller, + Key: key, + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{s.grantee}, + }) + s.Require().Error(err) + + // The NFT owner can grant under the legacy fallback. + _, err = s.msgServer.GrantRole(s.ctx, &types.MsgGrantRole{ + Signer: s.nftOwner, + Key: key, + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{s.grantee}, + }) + s.Require().NoError(err) + }) +} + +// TestGenesisRoundTrip verifies registry classes survive an export/import cycle. +func (s *RegistryClassAcceptanceTestSuite) TestGenesisRoundTrip() { + s.createClass("class-genesis", []types.RoleAuthorization{servicerRoleAuthorization()}) + + exported := s.registryKeeper.ExportGenesis(s.ctx) + s.Require().NoError(exported.Validate()) + s.Require().Len(exported.RegistryClasses, 1) + s.Require().Equal("class-genesis", exported.RegistryClasses[0].RegistryClassId) + + // Re-initialize into a fresh app and confirm the class is present. + freshApp := app.Setup(s.T()) + freshCtx := freshApp.BaseApp.NewContextLegacy(false, cmtproto.Header{Time: time.Now()}).WithBlockTime(time.Now()) + freshApp.RegistryKeeper.InitGenesis(freshCtx, exported) + + got, err := freshApp.RegistryKeeper.GetRegistryClass(freshCtx, "class-genesis") + s.Require().NoError(err) + s.Require().NotNil(got) + s.Require().Equal(s.maintainer, got.Maintainer) + s.Require().Len(got.RoleAuthorizations, 1) +} diff --git a/x/registry/keeper/role_change_accumulation_acceptance_test.go b/x/registry/keeper/role_change_accumulation_acceptance_test.go new file mode 100644 index 0000000000..39106264df --- /dev/null +++ b/x/registry/keeper/role_change_accumulation_acceptance_test.go @@ -0,0 +1,722 @@ +package keeper_test + +import ( + "strings" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "cosmossdk.io/x/nft" + nftkeeper "cosmossdk.io/x/nft/keeper" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz" + + "github.com/provenance-io/provenance/app" + "github.com/provenance-io/provenance/x/registry/keeper" + "github.com/provenance-io/provenance/x/registry/types" +) + +// RoleChangeAccumulationAcceptanceTestSuite implements the Controller +// authorization matrix using Option B: single-signer messages whose approvals accumulate in +// registry state until the role's policy is satisfied, at which point the change auto-applies. +// +// Required approvals for a Controller update: +// - Current Controller +// - Current Secured Party for eNote (only if set) +// - New Controller +// +// Unlike the native multi-signer model, every message here is single-signer, so each approval is +// delegable via authz (see TestControllerUpdate_Accumulation_ViaAuthz). +type RoleChangeAccumulationAcceptanceTestSuite struct { + suite.Suite + + app *app.App + ctx sdk.Context + + registryKeeper keeper.Keeper + nftKeeper nftkeeper.Keeper + msgServer types.MsgServer + + nftClass nft.Class + + nftOwner string + currentController string + newController string + securedParty string + stranger string +} + +func TestRoleChangeAccumulationAcceptanceTestSuite(t *testing.T) { + suite.Run(t, new(RoleChangeAccumulationAcceptanceTestSuite)) +} + +// genAddr generates a fresh bech32 account address. +func genAddr() string { + return sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String() +} + +func (s *RoleChangeAccumulationAcceptanceTestSuite) SetupTest() { + s.app = app.Setup(s.T()) + s.ctx = s.app.BaseApp.NewContextLegacy(false, cmtproto.Header{Time: time.Now()}).WithBlockTime(time.Now()) + + s.nftKeeper = s.app.NFTKeeper + s.registryKeeper = s.app.RegistryKeeper + s.msgServer = keeper.NewMsgServer(s.registryKeeper) + + s.nftOwner = genAddr() + s.currentController = genAddr() + s.newController = genAddr() + s.securedParty = genAddr() + s.stranger = genAddr() + + s.nftClass = nft.Class{Id: "accumulation-test-nft-class-id"} + s.nftKeeper.SaveClass(s.ctx, s.nftClass) + + // These tests exercise the CONTROLLER authorization policy, which is not a chain default. Install + // it as the module's default policy so classless entries are governed by it. + s.Require().NoError(s.registryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + })) +} + +func (s *RoleChangeAccumulationAcceptanceTestSuite) mintNFT(id string) *types.RegistryKey { + n := nft.NFT{ClassId: s.nftClass.Id, Id: id} + ownerAddr, err := sdk.AccAddressFromBech32(s.nftOwner) + s.Require().NoError(err) + s.Require().NoError(s.nftKeeper.Mint(s.ctx, n, ownerAddr)) + return &types.RegistryKey{AssetClassId: s.nftClass.Id, NftId: id} +} + +func (s *RoleChangeAccumulationAcceptanceTestSuite) setupRegistry(key *types.RegistryKey, roles []types.RolesEntry) { + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, roles, "")) +} + +// proposeNewController opens a pending GRANT of the CONTROLLER role to newController, signed by +// proposer, and returns the change id. +func (s *RoleChangeAccumulationAcceptanceTestSuite) proposeNewController(key *types.RegistryKey, proposer string) (string, bool) { + resp, err := s.msgServer.ProposeRoleChange(s.ctx, &types.MsgProposeRoleChange{ + Signer: proposer, + Key: key, + RoleUpdates: []types.RoleUpdate{{ + Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, + Addresses: []string{s.newController}, + }}, + }) + s.Require().NoError(err) + return resp.ChangeId, resp.Applied +} + +// approve records an approval for the pending change, signed by signer. +func (s *RoleChangeAccumulationAcceptanceTestSuite) approve(changeID, signer string) bool { + resp, err := s.msgServer.ApproveRoleChange(s.ctx, &types.MsgApproveRoleChange{ + Signer: signer, + ChangeId: changeID, + }) + s.Require().NoError(err) + return resp.Applied +} + +// proposeRevokeController opens a pending REVOKE of the CONTROLLER role from addr by proposing an +// empty desired-state for the role, signed by proposer, and returns the change id and whether it +// applied immediately. +func (s *RoleChangeAccumulationAcceptanceTestSuite) proposeRevokeController(key *types.RegistryKey, addr, proposer string) (string, bool) { + current := s.roleAddresses(key, types.RegistryRole_REGISTRY_ROLE_CONTROLLER) + desired := make([]string, 0, len(current)) + for _, a := range current { + if a != addr { + desired = append(desired, a) + } + } + resp, err := s.msgServer.ProposeRoleChange(s.ctx, &types.MsgProposeRoleChange{ + Signer: proposer, + Key: key, + RoleUpdates: []types.RoleUpdate{{ + Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, + Addresses: desired, + }}, + }) + s.Require().NoError(err) + return resp.ChangeId, resp.Applied +} + +func (s *RoleChangeAccumulationAcceptanceTestSuite) roleAddresses(key *types.RegistryKey, role types.RegistryRole) []string { + entry, err := s.registryKeeper.GetRegistry(s.ctx, key) + s.Require().NoError(err) + s.Require().NotNil(entry) + for _, re := range entry.Roles { + if re.Role == role { + return re.Addresses + } + } + return nil +} + +// --- Scenario A: Controller set, no Secured Party for eNote --------------------------- + +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestControllerSet_NoSecuredParty() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + + baseRoles := func() []types.RolesEntry { + return []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + } + } + + s.Run("happy path: current controller proposes, new controller approves", func() { + key := s.mintNFT("acc-a-happy") + s.setupRegistry(key, baseRoles()) + + changeID, applied := s.proposeNewController(key, s.currentController) + s.Require().False(applied, "should not apply with only the current controller's approval") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + + applied = s.approve(changeID, s.newController) + s.Require().True(applied, "current + new controller approvals should satisfy the policy") + s.Require().Contains(s.roleAddresses(key, controllerRole), s.newController) + }) + + s.Run("incomplete: only current controller approves", func() { + key := s.mintNFT("acc-a-cc-only") + s.setupRegistry(key, baseRoles()) + + _, applied := s.proposeNewController(key, s.currentController) + s.Require().False(applied) + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + }) + + s.Run("incomplete: only new controller approves", func() { + key := s.mintNFT("acc-a-nc-only") + s.setupRegistry(key, baseRoles()) + + _, applied := s.proposeNewController(key, s.newController) + s.Require().False(applied, "missing current controller approval") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + }) +} + +// --- Scenario B: Controller set, Secured Party for eNote set -------------------------- + +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestControllerSet_WithSecuredParty() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + securedPartyRole := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE + + baseRoles := func() []types.RolesEntry { + return []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + {Role: securedPartyRole, Addresses: []string{s.securedParty}}, + } + } + + s.Run("happy path: current controller, secured party, and new controller approve", func() { + key := s.mintNFT("acc-b-happy") + s.setupRegistry(key, baseRoles()) + + changeID, applied := s.proposeNewController(key, s.currentController) + s.Require().False(applied) + + applied = s.approve(changeID, s.securedParty) + s.Require().False(applied, "still missing new controller") + + applied = s.approve(changeID, s.newController) + s.Require().True(applied, "all three required approvals present") + s.Require().Contains(s.roleAddresses(key, controllerRole), s.newController) + }) + + s.Run("incomplete: current controller and secured party (missing new controller)", func() { + key := s.mintNFT("acc-b-cc-sp") + s.setupRegistry(key, baseRoles()) + + changeID, _ := s.proposeNewController(key, s.currentController) + applied := s.approve(changeID, s.securedParty) + s.Require().False(applied) + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + }) + + s.Run("incomplete: current controller and new controller (missing secured party)", func() { + key := s.mintNFT("acc-b-cc-nc") + s.setupRegistry(key, baseRoles()) + + changeID, _ := s.proposeNewController(key, s.currentController) + applied := s.approve(changeID, s.newController) + s.Require().False(applied, "secured party approval is required when it is set") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + }) + + s.Run("incomplete: secured party and new controller (missing current controller)", func() { + key := s.mintNFT("acc-b-sp-nc") + s.setupRegistry(key, baseRoles()) + + changeID, _ := s.proposeNewController(key, s.securedParty) + applied := s.approve(changeID, s.newController) + s.Require().False(applied, "current controller approval is always required (no unilateral takeover)") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + }) + + s.Run("incomplete: a stranger approves", func() { + key := s.mintNFT("acc-b-stranger") + s.setupRegistry(key, baseRoles()) + + changeID, _ := s.proposeNewController(key, s.currentController) + applied := s.approve(changeID, s.stranger) + s.Require().False(applied, "an unrelated approval does not satisfy the policy") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + + // The stranger is not referenced by the controller policy, so its approval must be + // ignored entirely rather than accumulating in the pending change's approval set. + pending, err := s.registryKeeper.GetPendingRoleChange(s.ctx, changeID) + s.Require().NoError(err) + s.Require().NotNil(pending) + s.Require().NotContains(pending.Approvals, s.stranger, "ineligible approvals are not recorded") + s.Require().Equal([]string{s.currentController}, pending.Approvals) + }) + + s.Run("incomplete: only current controller approves", func() { + key := s.mintNFT("acc-b-cc-only") + s.setupRegistry(key, baseRoles()) + + _, applied := s.proposeNewController(key, s.currentController) + s.Require().False(applied, "missing secured party and new controller approvals") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + }) + + s.Run("incomplete: only new controller approves", func() { + key := s.mintNFT("acc-b-nc-only") + s.setupRegistry(key, baseRoles()) + + _, applied := s.proposeNewController(key, s.newController) + s.Require().False(applied, "missing current controller and secured party approvals") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + }) + + s.Run("incomplete: only secured party approves", func() { + key := s.mintNFT("acc-b-sp-only") + s.setupRegistry(key, baseRoles()) + + changeID, applied := s.proposeNewController(key, s.securedParty) + s.Require().False(applied, "proposing as the secured party records only its own approval") + + // Re-stating the secured party's approval must remain insufficient. + applied = s.approve(changeID, s.securedParty) + s.Require().False(applied, "missing current controller and new controller approvals") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + }) +} + +// --- AuthZ delegation ----------------------------------------------------------------- +// +// The single-signer accumulation model is the whole reason Option B satisfies the authz +// requirement: because each MsgApproveRoleChange has exactly one signer, a party can grant another +// account authority to submit its approval via authz MsgExec. This is impossible with the native +// multi-signer MsgGrantRole (see authorization_acceptance_test.go, +// TestControllerUpdate_ViaAuthzGrants). + +func (s *RoleChangeAccumulationAcceptanceTestSuite) mustAddr(addr string) sdk.AccAddress { + a, err := sdk.AccAddressFromBech32(addr) + s.Require().NoError(err) + return a +} + +// grantApproveAuthz grants executor authority to submit MsgApproveRoleChange on behalf of granter. +func (s *RoleChangeAccumulationAcceptanceTestSuite) grantApproveAuthz(executor, granter string) { + auth := authz.NewGenericAuthorization(sdk.MsgTypeURL(&types.MsgApproveRoleChange{})) + s.Require().NoError(s.app.AuthzKeeper.SaveGrant(s.ctx, s.mustAddr(executor), s.mustAddr(granter), auth, nil)) +} + +// execApproveViaAuthz submits MsgApproveRoleChange (signed by granter) wrapped in a MsgExec run by +// executor. +func (s *RoleChangeAccumulationAcceptanceTestSuite) execApproveViaAuthz(executor, granter, changeID string) { + inner := &types.MsgApproveRoleChange{Signer: granter, ChangeId: changeID} + msgExec := authz.NewMsgExec(s.mustAddr(executor), []sdk.Msg{inner}) + _, err := s.app.AuthzKeeper.Exec(s.ctx, &msgExec) + s.Require().NoError(err, "authz must dispatch a single-signer approval") +} + +// grantProposeAuthz grants executor authority to submit MsgProposeRoleChange on behalf of granter. +func (s *RoleChangeAccumulationAcceptanceTestSuite) grantProposeAuthz(executor, granter string) { + auth := authz.NewGenericAuthorization(sdk.MsgTypeURL(&types.MsgProposeRoleChange{})) + s.Require().NoError(s.app.AuthzKeeper.SaveGrant(s.ctx, s.mustAddr(executor), s.mustAddr(granter), auth, nil)) +} + +// execProposeNewControllerViaAuthz submits MsgProposeRoleChange (signed by granter) to grant the +// CONTROLLER role to newController, wrapped in a MsgExec run by executor. Returns the change id. +func (s *RoleChangeAccumulationAcceptanceTestSuite) execProposeNewControllerViaAuthz(executor, granter string, key *types.RegistryKey) string { + inner := &types.MsgProposeRoleChange{ + Signer: granter, + Key: key, + RoleUpdates: []types.RoleUpdate{{ + Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, + Addresses: []string{s.newController}, + }}, + } + msgExec := authz.NewMsgExec(s.mustAddr(executor), []sdk.Msg{inner}) + _, err := s.app.AuthzKeeper.Exec(s.ctx, &msgExec) + s.Require().NoError(err, "authz must dispatch a single-signer proposal") + return types.NewPendingRoleChangeID(key, inner.RoleUpdates) +} + +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestControllerUpdate_Accumulation_ViaAuthz() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + securedPartyRole := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE + executor := genAddr() + + key := s.mintNFT("acc-authz") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + {Role: securedPartyRole, Addresses: []string{s.securedParty}}, + }) + + // Current controller proposes directly. + changeID, applied := s.proposeNewController(key, s.currentController) + s.Require().False(applied) + + // Secured party and new controller each delegate their approval to the executor via authz. + s.grantApproveAuthz(executor, s.securedParty) + s.grantApproveAuthz(executor, s.newController) + + s.execApproveViaAuthz(executor, s.securedParty, changeID) + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController, + "not yet applied after only the secured party's delegated approval") + + s.execApproveViaAuthz(executor, s.newController, changeID) + s.Require().Contains(s.roleAddresses(key, controllerRole), s.newController, + "change auto-applies once all required approvals (incl. authz-delegated ones) accumulate") + + // The pending change should have been cleaned up after applying. + pending, err := s.registryKeeper.GetPendingRoleChange(s.ctx, changeID) + s.Require().NoError(err) + s.Require().Nil(pending, "pending change should be removed after it applies") +} + +// TestControllerUpdate_NoSecuredParty_HappyPath_ViaAuthz proves the Scenario 1 happy path (no +// Secured Party set) also completes when both required approvals are delegated through authz. +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestControllerUpdate_NoSecuredParty_HappyPath_ViaAuthz() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + executor := genAddr() + + key := s.mintNFT("acc-authz-no-sp") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + }) + + // Both the current controller (proposer) and the new controller delegate via authz. + s.grantProposeAuthz(executor, s.currentController) + s.grantApproveAuthz(executor, s.newController) + + changeID := s.execProposeNewControllerViaAuthz(executor, s.currentController, key) + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController, + "not yet applied after only the current controller's delegated proposal") + + s.execApproveViaAuthz(executor, s.newController, changeID) + s.Require().Contains(s.roleAddresses(key, controllerRole), s.newController, + "current + new controller approvals (both authz-delegated) satisfy the policy") + + pending, err := s.registryKeeper.GetPendingRoleChange(s.ctx, changeID) + s.Require().NoError(err) + s.Require().Nil(pending, "pending change should be removed after it applies") +} + +// TestControllerUpdate_RejectMatrix_ViaAuthz re-runs the reject scenarios with every +// approval (and the proposal) delegated through authz MsgExec, proving that an incomplete set of +// authz-delegated approvals never satisfies the policy. A neutral executor carries each party's +// delegated authority, so no required party ever signs a transaction directly. +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestControllerUpdate_RejectMatrix_ViaAuthz() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + securedPartyRole := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE + + // authzApprovers opens the pending change as the first party (via authz) and submits the rest of + // the partial approver set (via authz), then asserts the change never applied. + authzApprovers := func(name string, withSecuredParty bool, approvers []string) { + s.Run(name, func() { + executor := genAddr() + key := s.mintNFT("acc-authz-reject-" + strings.ReplaceAll(name, "_", "-")) + + roles := []types.RolesEntry{{Role: controllerRole, Addresses: []string{s.currentController}}} + if withSecuredParty { + roles = append(roles, types.RolesEntry{Role: securedPartyRole, Addresses: []string{s.securedParty}}) + } + s.setupRegistry(key, roles) + + // Delegate every party's authority to the executor so nothing is signed directly. + for _, p := range approvers { + s.grantProposeAuthz(executor, p) + s.grantApproveAuthz(executor, p) + } + + // The first party opens the change via authz; the rest approve via authz. + changeID := s.execProposeNewControllerViaAuthz(executor, approvers[0], key) + for _, p := range approvers[1:] { + s.execApproveViaAuthz(executor, p, changeID) + } + + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController, + "incomplete authz-delegated approval set must not satisfy the policy") + pending, err := s.registryKeeper.GetPendingRoleChange(s.ctx, changeID) + s.Require().NoError(err) + s.Require().NotNil(pending, "the pending change should remain open while approvals are incomplete") + }) + } + + // Scenario 1: Controller set, no Secured Party for eNote. + authzApprovers("no_sp_only_current_controller", false, []string{s.currentController}) + authzApprovers("no_sp_only_new_controller", false, []string{s.newController}) + + // Scenario 2: Controller and Secured Party for eNote set. + authzApprovers("sp_only_current_controller", true, []string{s.currentController}) + authzApprovers("sp_only_new_controller", true, []string{s.newController}) + authzApprovers("sp_only_secured_party", true, []string{s.securedParty}) + authzApprovers("sp_current_controller_and_secured_party", true, []string{s.currentController, s.securedParty}) + authzApprovers("sp_current_controller_and_new_controller", true, []string{s.currentController, s.newController}) + authzApprovers("sp_secured_party_and_new_controller", true, []string{s.securedParty, s.newController}) +} + +// --- Scenario C: Controller revoke accumulation --------------------------------------- + +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestControllerRevoke_Accumulation() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + securedPartyRole := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE + + s.Run("single controller, no secured party: applies on proposer approval", func() { + key := s.mintNFT("acc-c-single") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + }) + + _, applied := s.proposeRevokeController(key, s.currentController, s.currentController) + s.Require().True(applied, "the sole current controller's approval satisfies a revoke") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.currentController) + }) + + s.Run("secured party set: requires current controller and secured party", func() { + key := s.mintNFT("acc-c-with-sp") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + {Role: securedPartyRole, Addresses: []string{s.securedParty}}, + }) + + changeID, applied := s.proposeRevokeController(key, s.currentController, s.currentController) + s.Require().False(applied, "secured party approval still required for a revoke") + s.Require().Contains(s.roleAddresses(key, controllerRole), s.currentController) + + applied = s.approve(changeID, s.securedParty) + s.Require().True(applied, "current controller + secured party satisfy the revoke") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.currentController) + }) +} + +// --- Invalidation: stale approvals are voided when role holders change underneath ------ +// +// The accumulation engine re-resolves roles against live registry state on every approval, so an +// approval recorded by a party that is no longer the current role holder cannot satisfy the policy. +// This is the invalidation guarantee without a separate expiry mechanism. + +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestControllerUpdate_InvalidationOnRoleChange() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + rotatedController := genAddr() + + key := s.mintNFT("acc-invalidation") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + }) + + // Current controller proposes; only their approval is recorded so far. + changeID, applied := s.proposeNewController(key, s.currentController) + s.Require().False(applied) + + // The controller is rotated out from under the pending change (e.g. via a separate completed + // flow). The pending change still carries the now-stale currentController approval. + s.Require().NoError(s.registryKeeper.RevokeRole(s.ctx, key, controllerRole, []string{s.currentController})) + s.Require().NoError(s.registryKeeper.GrantRole(s.ctx, key, controllerRole, []string{rotatedController})) + + // The new controller approving is no longer enough: the stale approval no longer counts as the + // current controller, so the policy is not satisfied. + applied = s.approve(changeID, s.newController) + s.Require().False(applied, "stale current-controller approval is voided after the role holder changed") + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + + // Once the live current controller approves, the policy is satisfied and the change applies. + applied = s.approve(changeID, rotatedController) + s.Require().True(applied, "the live current controller's approval re-satisfies the policy") + s.Require().Contains(s.roleAddresses(key, controllerRole), s.newController) +} + +// --- Edge cases ----------------------------------------------------------------------- + +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestPendingChange_EdgeCases() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + securedPartyRole := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE + + s.Run("duplicate approval is idempotent", func() { + key := s.mintNFT("acc-edge-dup") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + {Role: securedPartyRole, Addresses: []string{s.securedParty}}, + }) + + changeID, applied := s.proposeNewController(key, s.currentController) + s.Require().False(applied) + + // The current controller approving again must not double-count or apply the change. + applied = s.approve(changeID, s.currentController) + s.Require().False(applied) + + pending, err := s.registryKeeper.GetPendingRoleChange(s.ctx, changeID) + s.Require().NoError(err) + s.Require().NotNil(pending) + s.Require().Equal([]string{s.currentController}, pending.Approvals, "approver recorded exactly once") + }) + + s.Run("approving a non-existent change errors", func() { + _, err := s.msgServer.ApproveRoleChange(s.ctx, &types.MsgApproveRoleChange{ + Signer: s.currentController, + ChangeId: "does-not-exist", + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "pending role change") + }) + + s.Run("ineligible proposer cannot open a pending change", func() { + key := s.mintNFT("acc-edge-ineligible-proposer") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + {Role: securedPartyRole, Addresses: []string{s.securedParty}}, + }) + + // The stranger is not a required party for the controller policy, so it must not be able + // to open (and persist) a new pending change. + resp, err := s.msgServer.ProposeRoleChange(s.ctx, &types.MsgProposeRoleChange{ + Signer: s.stranger, + Key: key, + RoleUpdates: []types.RoleUpdate{{ + Role: controllerRole, + Addresses: []string{s.newController}, + }}, + }) + s.Require().Error(err) + s.Require().Contains(err.Error(), "not eligible") + s.Require().Nil(resp) + + // No pending change should have been persisted for this key. + changes, _, err := s.registryKeeper.GetPendingRoleChanges(s.ctx, nil, key) + s.Require().NoError(err) + s.Require().Empty(changes, "no pending change is created for an ineligible proposer") + }) + + s.Run("registry removed underneath cleans up the pending change", func() { + key := s.mintNFT("acc-edge-removed") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + {Role: securedPartyRole, Addresses: []string{s.securedParty}}, + }) + + changeID, applied := s.proposeNewController(key, s.currentController) + s.Require().False(applied) + + s.Require().NoError(s.registryKeeper.DeleteRegistry(s.ctx, key)) + + _, err := s.msgServer.ApproveRoleChange(s.ctx, &types.MsgApproveRoleChange{ + Signer: s.securedParty, + ChangeId: changeID, + }) + s.Require().Error(err) + + pending, err := s.registryKeeper.GetPendingRoleChange(s.ctx, changeID) + s.Require().NoError(err) + s.Require().Nil(pending, "the orphaned pending change is removed") + }) +} + +// proposeBatch opens a pending change for an arbitrary batch of desired-state role updates, signed +// by proposer, and returns the change id and whether it applied immediately. +func (s *RoleChangeAccumulationAcceptanceTestSuite) proposeBatch(key *types.RegistryKey, proposer string, updates []types.RoleUpdate) (string, bool) { + resp, err := s.msgServer.ProposeRoleChange(s.ctx, &types.MsgProposeRoleChange{ + Signer: proposer, + Key: key, + RoleUpdates: updates, + }) + s.Require().NoError(err) + return resp.ChangeId, resp.Applied +} + +// --- Atomic grant+revoke: controller rotation in a single pending change --------------- +// +// A controller rotation (remove the old controller, add the new one) is expressed as a single +// desired-state role update. The grant and revoke are inseparable: the whole change applies +// atomically once the role's policy is satisfied, never leaving the role half-updated. + +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestControllerRotation_AtomicGrantRevoke() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + securedPartyRole := types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE + + key := s.mintNFT("acc-rotation") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + {Role: securedPartyRole, Addresses: []string{s.securedParty}}, + }) + + // Desired state replaces the controller entirely: drops currentController, adds newController. + rotation := []types.RoleUpdate{{Role: controllerRole, Addresses: []string{s.newController}}} + + changeID, applied := s.proposeBatch(key, s.currentController, rotation) + s.Require().False(applied) + + applied = s.approve(changeID, s.securedParty) + s.Require().False(applied, "still missing the new controller's approval") + + // Nothing is half-applied while pending: the old controller is still present. + s.Require().Contains(s.roleAddresses(key, controllerRole), s.currentController) + s.Require().NotContains(s.roleAddresses(key, controllerRole), s.newController) + + applied = s.approve(changeID, s.newController) + s.Require().True(applied, "current controller + secured party + new controller satisfy the rotation") + + // The grant and revoke applied together: role is now exactly the new controller. + s.Require().Equal([]string{s.newController}, s.roleAddresses(key, controllerRole)) +} + +// --- Atomic batch across roles: policy role + NFT-owner-fallback role ------------------ +// +// A single pending change can carry updates to several roles. It applies only when every affected +// role's gate is satisfied (policy for governed roles, NFT ownership for the rest), and all updates +// apply together. + +func (s *RoleChangeAccumulationAcceptanceTestSuite) TestBatchRoleUpdate_AcrossRoles_AtomicApply() { + controllerRole := types.RegistryRole_REGISTRY_ROLE_CONTROLLER + servicerRole := types.RegistryRole_REGISTRY_ROLE_SERVICER + oldServicer := genAddr() + newServicer := genAddr() + + key := s.mintNFT("acc-batch-roles") + s.setupRegistry(key, []types.RolesEntry{ + {Role: controllerRole, Addresses: []string{s.currentController}}, + {Role: servicerRole, Addresses: []string{oldServicer}}, + }) + + // One batch: rotate the controller (policy-governed) and replace the servicer (no policy, so it + // falls back to NFT ownership). + batch := []types.RoleUpdate{ + {Role: controllerRole, Addresses: []string{s.newController}}, + {Role: servicerRole, Addresses: []string{newServicer}}, + } + + changeID, applied := s.proposeBatch(key, s.currentController, batch) + s.Require().False(applied) + + // Both controller approvals are present (no secured party set), but the servicer update still + // needs the NFT owner's approval, so the atomic batch must NOT apply. + applied = s.approve(changeID, s.newController) + s.Require().False(applied, "servicer update still requires the NFT owner's approval") + s.Require().Equal([]string{s.currentController}, s.roleAddresses(key, controllerRole)) + s.Require().Equal([]string{oldServicer}, s.roleAddresses(key, servicerRole)) + + // The NFT owner approves, satisfying the servicer (owner-fallback) gate. Now every gate is met + // and the whole batch applies atomically. + applied = s.approve(changeID, s.nftOwner) + s.Require().True(applied, "all gates satisfied: controller policy and servicer owner-fallback") + s.Require().Equal([]string{s.newController}, s.roleAddresses(key, controllerRole)) + s.Require().Equal([]string{newServicer}, s.roleAddresses(key, servicerRole)) +} diff --git a/x/registry/keeper/role_event_query_acceptance_test.go b/x/registry/keeper/role_event_query_acceptance_test.go new file mode 100644 index 0000000000..baaf322e9d --- /dev/null +++ b/x/registry/keeper/role_event_query_acceptance_test.go @@ -0,0 +1,406 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + abci "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "cosmossdk.io/x/nft" + nftkeeper "cosmossdk.io/x/nft/keeper" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/provenance-io/provenance/app" + "github.com/provenance-io/provenance/x/registry/keeper" + "github.com/provenance-io/provenance/x/registry/types" +) + +// RoleEventAndQueryAcceptanceTestSuite covers Phase C4 (the comprehensive EventRoleUpdated, with +// registry_class_id / previous_addresses / signers) and Phase C5 (the read-only ValidateRoleChange +// dry-run query). +type RoleEventAndQueryAcceptanceTestSuite struct { + suite.Suite + + app *app.App + ctx sdk.Context + + registryKeeper keeper.Keeper + nftKeeper nftkeeper.Keeper + msgServer types.MsgServer + queryServer *keeper.QueryServer + + nftClass nft.Class + + nftOwner string + currentController string + newController string + securedParty string + stranger string +} + +func TestRoleEventAndQueryAcceptanceTestSuite(t *testing.T) { + suite.Run(t, new(RoleEventAndQueryAcceptanceTestSuite)) +} + +func (s *RoleEventAndQueryAcceptanceTestSuite) SetupTest() { + s.app = app.Setup(s.T()) + s.ctx = s.app.BaseApp.NewContextLegacy(false, cmtproto.Header{Time: time.Now()}).WithBlockTime(time.Now()) + + s.nftKeeper = s.app.NFTKeeper + s.registryKeeper = s.app.RegistryKeeper + s.msgServer = keeper.NewMsgServer(s.registryKeeper) + s.queryServer = keeper.NewQueryServer(s.registryKeeper) + + s.nftOwner = genAddr() + s.currentController = genAddr() + s.newController = genAddr() + s.securedParty = genAddr() + s.stranger = genAddr() + + s.nftClass = nft.Class{Id: "event-query-test-nft-class"} + s.nftKeeper.SaveClass(s.ctx, s.nftClass) + + // Install the CONTROLLER policy as the module default so classless entries are policy-governed. + s.Require().NoError(s.registryKeeper.SetParams(s.ctx, types.Params{ + RoleAuthorizations: types.ControllerRoleAuthorizations(), + })) +} + +func (s *RoleEventAndQueryAcceptanceTestSuite) mintNFT(id string) *types.RegistryKey { + n := nft.NFT{ClassId: s.nftClass.Id, Id: id} + ownerAddr, err := sdk.AccAddressFromBech32(s.nftOwner) + s.Require().NoError(err) + s.Require().NoError(s.nftKeeper.Mint(s.ctx, n, ownerAddr)) + return &types.RegistryKey{AssetClassId: s.nftClass.Id, NftId: id} +} + +// resetEvents installs a fresh event manager so each scenario inspects only its own events. +func (s *RoleEventAndQueryAcceptanceTestSuite) resetEvents() { + s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) +} + +// roleUpdatedEvents returns all EventRoleUpdated emitted since the last resetEvents. +func (s *RoleEventAndQueryAcceptanceTestSuite) roleUpdatedEvents() []*types.EventRoleUpdated { + var out []*types.EventRoleUpdated + for _, e := range s.ctx.EventManager().Events() { + if e.Type != "provenance.registry.v1.EventRoleUpdated" { + continue + } + msg, err := sdk.ParseTypedEvent(abci.Event{Type: e.Type, Attributes: e.Attributes}) + s.Require().NoError(err) + ev, ok := msg.(*types.EventRoleUpdated) + s.Require().True(ok) + out = append(out, ev) + } + return out +} + +// --- Phase C4: EventRoleUpdated ----------------------------------------------------------------- + +// TestEventRoleUpdated_LegacyPath: a role change authorized by the NFT owner (no policy for the +// role) emits EventRoleUpdated with the NFT-owner signer and an empty registry_class_id. +func (s *RoleEventAndQueryAcceptanceTestSuite) TestEventRoleUpdated_LegacyPath() { + key := s.mintNFT("evt-legacy") + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, nil, "")) + grantee := genAddr() + + s.resetEvents() + // SERVICER has no policy (only CONTROLLER does), so this uses the NFT-owner fallback. + _, err := s.msgServer.GrantRole(s.ctx, &types.MsgGrantRole{ + Signer: s.nftOwner, + Key: key, + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{grantee}, + }) + s.Require().NoError(err) + + evts := s.roleUpdatedEvents() + s.Require().Len(evts, 1) + ev := evts[0] + s.Require().Equal(key.NftId, ev.NftId) + s.Require().Equal(key.AssetClassId, ev.AssetClassId) + s.Require().Equal("", ev.RegistryClassId) + s.Require().Equal("SERVICER", ev.Role) + s.Require().Equal([]string{grantee}, ev.Addresses) + s.Require().Empty(ev.PreviousAddresses) + s.Require().Len(ev.Signers, 1) + s.Require().Equal("NFT_ROLE_NFT_OWNER", ev.Signers[0].Role) + s.Require().Equal("ASSIGNMENT_CURRENT", ev.Signers[0].Assignment) + s.Require().Equal([]string{s.nftOwner}, ev.Signers[0].Addresses) +} + +// TestEventRoleUpdated_PolicyAccumulation: a CONTROLLER change applied via the propose/approve flow +// emits EventRoleUpdated whose signers describe the satisfying policy path (current + secured party +// + new controller) and whose previous/current addresses capture the transition. +func (s *RoleEventAndQueryAcceptanceTestSuite) TestEventRoleUpdated_PolicyAccumulation() { + key := s.mintNFT("evt-policy") + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.currentController}}, + {Role: types.RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE, Addresses: []string{s.securedParty}}, + }, "")) + + resp, err := s.msgServer.ProposeRoleChange(s.ctx, &types.MsgProposeRoleChange{ + Signer: s.currentController, + Key: key, + RoleUpdates: []types.RoleUpdate{{ + Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, + Addresses: []string{s.newController}, + }}, + }) + s.Require().NoError(err) + s.Require().False(resp.Applied) + + _, err = s.msgServer.ApproveRoleChange(s.ctx, &types.MsgApproveRoleChange{Signer: s.securedParty, ChangeId: resp.ChangeId}) + s.Require().NoError(err) + + // The applying approval emits the EventRoleUpdated; isolate it. + s.resetEvents() + applyResp, err := s.msgServer.ApproveRoleChange(s.ctx, &types.MsgApproveRoleChange{Signer: s.newController, ChangeId: resp.ChangeId}) + s.Require().NoError(err) + s.Require().True(applyResp.Applied) + + evts := s.roleUpdatedEvents() + s.Require().Len(evts, 1) + ev := evts[0] + s.Require().Equal("CONTROLLER", ev.Role) + s.Require().Equal([]string{s.newController}, ev.Addresses) + s.Require().Equal([]string{s.currentController}, ev.PreviousAddresses) + + // Signers: current controller (CURRENT), secured party for eNote (CURRENT), new controller (NEW). + got := map[string][]string{} + for _, sgn := range ev.Signers { + got[sgn.Role+"|"+sgn.Assignment] = sgn.Addresses + } + s.Require().Equal([]string{s.currentController}, got["REGISTRY_ROLE_CONTROLLER|ASSIGNMENT_CURRENT"]) + s.Require().Equal([]string{s.securedParty}, got["REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE|ASSIGNMENT_CURRENT"]) + s.Require().Equal([]string{s.newController}, got["REGISTRY_ROLE_CONTROLLER|ASSIGNMENT_NEW"]) +} + +// TestEventRoleUpdated_Revoke: a revoke (removing an address from a role) emits EventRoleUpdated +// with the resulting (empty) address set and the prior addresses, authorized via the NFT-owner +// fallback for a role with no policy. +func (s *RoleEventAndQueryAcceptanceTestSuite) TestEventRoleUpdated_Revoke() { + key := s.mintNFT("evt-revoke") + servicer := genAddr() + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, Addresses: []string{servicer}}, + }, "")) + + s.resetEvents() + // SERVICER has no policy, so the NFT owner authorizes the revoke. + _, err := s.msgServer.RevokeRole(s.ctx, &types.MsgRevokeRole{ + Signer: s.nftOwner, + Key: key, + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{servicer}, + }) + s.Require().NoError(err) + + evts := s.roleUpdatedEvents() + s.Require().Len(evts, 1) + ev := evts[0] + s.Require().Equal("SERVICER", ev.Role) + s.Require().Empty(ev.Addresses) + s.Require().Equal([]string{servicer}, ev.PreviousAddresses) + s.Require().Len(ev.Signers, 1) + s.Require().Equal("NFT_ROLE_NFT_OWNER", ev.Signers[0].Role) + s.Require().Equal([]string{s.nftOwner}, ev.Signers[0].Addresses) +} + +// TestEventRoleUpdated_RegistryClassId: an entry registered under a class carries that class id on +// the event. +func (s *RoleEventAndQueryAcceptanceTestSuite) TestEventRoleUpdated_RegistryClassId() { + maintainer := genAddr() + _, err := s.msgServer.CreateRegistryClass(s.ctx, &types.MsgCreateRegistryClass{ + Signer: maintainer, + RegistryClassId: "evt-class", + AssetClassId: s.nftClass.Id, + Maintainer: maintainer, + RoleAuthorizations: []types.RoleAuthorization{servicerRoleAuthorization()}, + }) + s.Require().NoError(err) + + key := s.mintNFT("evt-classed") + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.currentController}}, + }, "evt-class")) + + grantee := genAddr() + s.resetEvents() + // The class policy lets the current controller manage servicers single-handedly. + _, err = s.msgServer.GrantRole(s.ctx, &types.MsgGrantRole{ + Signer: s.currentController, + Key: key, + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{grantee}, + }) + s.Require().NoError(err) + + evts := s.roleUpdatedEvents() + s.Require().Len(evts, 1) + ev := evts[0] + s.Require().Equal("evt-class", ev.RegistryClassId) + s.Require().Equal("SERVICER", ev.Role) + s.Require().Empty(ev.PreviousAddresses) + s.Require().Equal([]string{grantee}, ev.Addresses) + s.Require().Len(ev.Signers, 1) + s.Require().Equal("REGISTRY_ROLE_CONTROLLER", ev.Signers[0].Role) + s.Require().Equal("ASSIGNMENT_CURRENT", ev.Signers[0].Assignment) + s.Require().Equal([]string{s.currentController}, ev.Signers[0].Addresses) +} + +// TestSetRoles_AdditionsOnlyForNewAssignment: MsgSetRoles takes the full desired address set, but +// the authorization engine's ASSIGNMENT_NEW must resolve only the newly-added addresses. A policy +// that requires the incoming (NEW) member to sign must be satisfiable single-signer by that member +// even when the desired set also contains already-current members. +func (s *RoleEventAndQueryAcceptanceTestSuite) TestSetRoles_AdditionsOnlyForNewAssignment() { + // Policy: a SERVICER may be added if the newly-assigned servicer signs (SERVICER@NEW). + selfAddServicer := types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{{ + Description: "a new servicer may add themselves", + Signatures: []*types.SignatureRequirement{{ + Type: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL, + Roles: []*types.RoleAssignment{{ + RoleSelector: &types.RoleAssignment_RegistryRole{ + RegistryRole: types.RegistryRole_REGISTRY_ROLE_SERVICER, + }, + Assignment: types.Assignment_ASSIGNMENT_NEW, + }}, + }}, + }}, + } + maintainer := genAddr() + _, err := s.msgServer.CreateRegistryClass(s.ctx, &types.MsgCreateRegistryClass{ + Signer: maintainer, + RegistryClassId: "servicer-class", + AssetClassId: s.nftClass.Id, + Maintainer: maintainer, + RoleAuthorizations: []types.RoleAuthorization{selfAddServicer}, + }) + s.Require().NoError(err) + + existingServicer := genAddr() + newServicer := genAddr() + key := s.mintNFT("evt-additions") + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, Addresses: []string{existingServicer}}, + }, "servicer-class")) + + s.resetEvents() + // Desired state is [existing, new]; only the addition (newServicer) needs to sign. Before the + // additions fix this errored because ASSIGNMENT_NEW resolved to both addresses. + _, err = s.msgServer.SetRoles(s.ctx, &types.MsgSetRoles{ + Signer: newServicer, + Key: key, + RoleUpdates: []types.RoleUpdate{{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{existingServicer, newServicer}, + }}, + }) + s.Require().NoError(err) + + evts := s.roleUpdatedEvents() + s.Require().Len(evts, 1) + ev := evts[0] + s.Require().Equal("SERVICER", ev.Role) + s.Require().Equal([]string{existingServicer, newServicer}, ev.Addresses) + s.Require().Equal([]string{existingServicer}, ev.PreviousAddresses) + s.Require().Len(ev.Signers, 1) + s.Require().Equal("REGISTRY_ROLE_SERVICER", ev.Signers[0].Role) + s.Require().Equal("ASSIGNMENT_NEW", ev.Signers[0].Assignment) + s.Require().Equal([]string{newServicer}, ev.Signers[0].Addresses) +} + +// --- Phase C5: ValidateRoleChange query --------------------------------------------------------- + +func (s *RoleEventAndQueryAcceptanceTestSuite) controllerUpdate() []types.RoleUpdate { + return []types.RoleUpdate{{ + Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, + Addresses: []string{s.newController}, + }} +} + +func (s *RoleEventAndQueryAcceptanceTestSuite) TestValidateRoleChange_Authorized() { + key := s.mintNFT("vrc-ok") + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.currentController}}, + }, "")) + + res, err := s.queryServer.ValidateRoleChange(s.ctx, &types.QueryValidateRoleChangeRequest{ + Key: key, + RoleUpdates: s.controllerUpdate(), + Approvers: []string{s.currentController, s.newController}, + }) + s.Require().NoError(err) + s.Require().True(res.Authorized) + s.Require().Empty(res.Error) +} + +func (s *RoleEventAndQueryAcceptanceTestSuite) TestValidateRoleChange_MissingApprover() { + key := s.mintNFT("vrc-missing") + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, []types.RolesEntry{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{s.currentController}}, + }, "")) + + // Only the current controller approves; the new controller's approval is still outstanding. + res, err := s.queryServer.ValidateRoleChange(s.ctx, &types.QueryValidateRoleChangeRequest{ + Key: key, + RoleUpdates: s.controllerUpdate(), + Approvers: []string{s.currentController}, + }) + s.Require().NoError(err) + s.Require().False(res.Authorized) + s.Require().NotEmpty(res.Error) + s.Require().Contains(res.Error, "CONTROLLER") +} + +func (s *RoleEventAndQueryAcceptanceTestSuite) TestValidateRoleChange_LegacyFallback() { + key := s.mintNFT("vrc-legacy") + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, nil, "")) + + update := []types.RoleUpdate{{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Addresses: []string{genAddr()}, + }} + + s.Run("NFT owner approves", func() { + res, err := s.queryServer.ValidateRoleChange(s.ctx, &types.QueryValidateRoleChangeRequest{ + Key: key, + RoleUpdates: update, + Approvers: []string{s.nftOwner}, + }) + s.Require().NoError(err) + s.Require().True(res.Authorized) + s.Require().Empty(res.Error) + }) + + s.Run("non-owner is rejected", func() { + res, err := s.queryServer.ValidateRoleChange(s.ctx, &types.QueryValidateRoleChangeRequest{ + Key: key, + RoleUpdates: update, + Approvers: []string{s.stranger}, + }) + s.Require().NoError(err) + s.Require().False(res.Authorized) + s.Require().NotEmpty(res.Error) + }) +} + +func (s *RoleEventAndQueryAcceptanceTestSuite) TestValidateRoleChange_InvalidRequest() { + s.Run("nil request", func() { + _, err := s.queryServer.ValidateRoleChange(s.ctx, nil) + s.Require().Error(err) + }) + + s.Run("no role updates", func() { + key := s.mintNFT("vrc-empty") + s.Require().NoError(s.registryKeeper.CreateRegistry(s.ctx, key, nil, "")) + _, err := s.queryServer.ValidateRoleChange(s.ctx, &types.QueryValidateRoleChangeRequest{Key: key}) + s.Require().Error(err) + }) +} diff --git a/x/registry/spec/examples/README.md b/x/registry/spec/examples/README.md new file mode 100644 index 0000000000..580fece7a8 --- /dev/null +++ b/x/registry/spec/examples/README.md @@ -0,0 +1,27 @@ +# Registry class examples + +This directory holds example registry classes that can be created with the registry CLI. + +## `example_registry_class.json` + +A complete example registry class expressing the participant role policies as ordinary +`role_authorizations` data: Originator, Lien Owner (with foreclosure), +Controller (with foreclosure), Secured Party for Lien, Secured Party for eNote, Pledgee, Servicer, +and Sub-servicer. + +These policies are evaluated by the registry's authorization engine; none of them are hard-coded into +the chain. A maintainer installs them per asset class: + +```bash +provenanced tx registry create-registry-class example_registry_class.json --from +``` + +Before submitting, set `registry_class_id`, `asset_class_id`, and `maintainer` to your values (the +`maintainer` must equal the `--from` signer, or it can be omitted to default to that signer). + +The file is kept in sync with the policy builders in +`x/registry/keeper/participant_role_policies_acceptance_test.go`; regenerate it with: + +```bash +REGEN_EXAMPLE_FIXTURE=1 go test ./x/registry/keeper/ -run TestParticipantRolePoliciesAcceptanceTestSuite/TestExampleFixtureInSync +``` diff --git a/x/registry/spec/examples/example_registry_class.json b/x/registry/spec/examples/example_registry_class.json new file mode 100644 index 0000000000..a54c9ed1de --- /dev/null +++ b/x/registry/spec/examples/example_registry_class.json @@ -0,0 +1 @@ +{"registry_class_id":"loan-registry-v1","asset_class_id":"loan.asset","maintainer":"pb1maintainerplaceholder0000000000000000000","role_authorizations":[{"role":"REGISTRY_ROLE_ORIGINATOR","authorizations":[{"description":"Assign originator (requires current and new originator approval)","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"role_priority":{"entries":[{"registry_role":"REGISTRY_ROLE_ORIGINATOR"},{"nft_role":"NFT_ROLE_NFT_OWNER"}]},"assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"registry_role":"REGISTRY_ROLE_ORIGINATOR","assignment":"ASSIGNMENT_NEW"}]}]}]},{"role":"REGISTRY_ROLE_LIEN_OWNER","authorizations":[{"description":"Transfer requiring current lien owner approval","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"role_priority":{"entries":[{"registry_role":"REGISTRY_ROLE_LIEN_OWNER"},{"nft_role":"NFT_ROLE_NFT_OWNER"}]},"assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_LIEN_OWNER","assignment":"ASSIGNMENT_NEW"}]}]},{"description":"Foreclosure: Secured Party for Lien can unilaterally become Lien Owner in case of default","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_LIEN_OWNER","assignment":"ASSIGNMENT_NEW"}]}]}]},{"role":"REGISTRY_ROLE_CONTROLLER","authorizations":[{"description":"Transfer requiring current controller approval","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"role_priority":{"entries":[{"registry_role":"REGISTRY_ROLE_CONTROLLER"},{"nft_role":"NFT_ROLE_NFT_OWNER"}]},"assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_CONTROLLER","assignment":"ASSIGNMENT_NEW"}]}]},{"description":"Foreclosure: Secured Party for eNote can unilaterally become Controller in case of default","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_CONTROLLER","assignment":"ASSIGNMENT_NEW"}]}]}]},{"role":"REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN","authorizations":[{"description":"Update by current lien owner","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"role_priority":{"entries":[{"registry_role":"REGISTRY_ROLE_LIEN_OWNER"},{"nft_role":"NFT_ROLE_NFT_OWNER"}]},"assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN","assignment":"ASSIGNMENT_NEW"}]}]},{"description":"Update by current secured party for lien","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN","assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN","assignment":"ASSIGNMENT_NEW"}]}]}]},{"role":"REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE","authorizations":[{"description":"Update by current controller","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"role_priority":{"entries":[{"registry_role":"REGISTRY_ROLE_CONTROLLER"},{"nft_role":"NFT_ROLE_NFT_OWNER"}]},"assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE","assignment":"ASSIGNMENT_NEW"}]}]},{"description":"Update by current secured party for eNote","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE","assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE","assignment":"ASSIGNMENT_NEW"}]}]}]},{"role":"REGISTRY_ROLE_PLEDGEE","authorizations":[{"description":"Update pledgee with value owner approval","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"nft_role":"NFT_ROLE_NFT_OWNER","assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"registry_role":"REGISTRY_ROLE_PLEDGEE","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_PLEDGEE","assignment":"ASSIGNMENT_NEW"}]}]}]},{"role":"REGISTRY_ROLE_SERVICER","authorizations":[{"description":"Update servicer with owner/controller approval","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"role_priority":{"entries":[{"registry_role":"REGISTRY_ROLE_CONTROLLER"},{"nft_role":"NFT_ROLE_NFT_OWNER"}]},"assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"role_priority":{"entries":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE"},{"registry_role":"REGISTRY_ROLE_PLEDGEE"}]},"assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_SERVICER","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_SERVICER","assignment":"ASSIGNMENT_NEW"}]}]}]},{"role":"REGISTRY_ROLE_SUBSERVICER","authorizations":[{"description":"Update sub-servicer with owner/controller and servicer approval","signatures":[{"type":"SIGNATURE_TYPE_REQUIRED_ALL","roles":[{"role_priority":{"entries":[{"registry_role":"REGISTRY_ROLE_CONTROLLER"},{"nft_role":"NFT_ROLE_NFT_OWNER"}]},"assignment":"ASSIGNMENT_CURRENT"}]},{"type":"SIGNATURE_TYPE_REQUIRED_ALL_IF_SET","roles":[{"role_priority":{"entries":[{"registry_role":"REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE"},{"registry_role":"REGISTRY_ROLE_PLEDGEE"}]},"assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_SERVICER","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_SUBSERVICER","assignment":"ASSIGNMENT_CURRENT"},{"registry_role":"REGISTRY_ROLE_SUBSERVICER","assignment":"ASSIGNMENT_NEW"}]}]}]}]} diff --git a/x/registry/types/authorization.go b/x/registry/types/authorization.go new file mode 100644 index 0000000000..34fd606f41 --- /dev/null +++ b/x/registry/types/authorization.go @@ -0,0 +1,129 @@ +package types + +import ( + "fmt" + + "github.com/provenance-io/provenance/internal/provutils" +) + +// Validate returns an error if this SignatureType is not a defined enum entry, or is unspecified. +func (t SignatureType) Validate() error { + if err := provutils.EnumValidateExists(t, SignatureType_name); err != nil { + return err + } + if t == SignatureType_SIGNATURE_TYPE_UNSPECIFIED { + return fmt.Errorf("cannot be unspecified") + } + return nil +} + +// Validate returns an error if this NftRole is not a defined enum entry, or is unspecified. +func (r NftRole) Validate() error { + if err := provutils.EnumValidateExists(r, NftRole_name); err != nil { + return err + } + if r == NftRole_NFT_ROLE_UNSPECIFIED { + return fmt.Errorf("cannot be unspecified") + } + return nil +} + +// Validate returns an error if this Assignment is not a defined enum entry, or is unspecified. +func (a Assignment) Validate() error { + if err := provutils.EnumValidateExists(a, Assignment_name); err != nil { + return err + } + if a == Assignment_ASSIGNMENT_UNSPECIFIED { + return fmt.Errorf("cannot be unspecified") + } + return nil +} + +// IsCurrent reports whether this assignment resolves currently-held addresses (the CURRENT* family) +// rather than incoming new addresses (the NEW* family). NftRole selectors are only valid with the +// CURRENT* family because the registry module cannot assign NFT-module roles. +func (a Assignment) IsCurrent() bool { + switch a { + case Assignment_ASSIGNMENT_CURRENT, + Assignment_ASSIGNMENT_CURRENT_ALL, + Assignment_ASSIGNMENT_CURRENT_ANY: + return true + default: + return false + } +} + +// ControllerRoleAuthorizations returns an example CONTROLLER authorization policy. +// This is NOT the default chain behavior: by default the registry module has no role policies and +// every role change falls back to legacy NFT-owner authorization. This policy set is provided as a +// reusable example that governance can install via MsgUpdateParams, or that a registry-class +// maintainer can adopt for an asset class. +func ControllerRoleAuthorizations() []RoleAuthorization { + return []RoleAuthorization{ + controllerRoleAuthorization(), + } +} + +// RoleAuthorizationMapFrom builds a map of RegistryRole → RoleAuthorization from the given slice. +// The last entry wins if a role appears more than once. +func RoleAuthorizationMapFrom(auths []RoleAuthorization) map[RegistryRole]RoleAuthorization { + m := make(map[RegistryRole]RoleAuthorization, len(auths)) + for _, a := range auths { + m[a.Role] = a + } + return m +} + +// controllerRoleAuthorization defines the CONTROLLER role authorization policy. +// +// A Controller update requires all of the following to sign: +// - the current controller (or the NFT owner if no controller is set); +// - the current Secured Party for eNote, if one is set; +// - the incoming new controller. +// +// The current controller's signature is always required: there is no path that lets any other +// party assume control unilaterally. +func controllerRoleAuthorization() RoleAuthorization { + return RoleAuthorization{ + Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, + Authorizations: []*Authorization{ + { + Description: "Transfer requiring current controller approval", + Signatures: []*SignatureRequirement{ + { + // The current authority (controller if set, otherwise NFT owner) must sign. + Type: SignatureType_SIGNATURE_TYPE_REQUIRED_ALL, + Roles: []*RoleAssignment{ + { + RoleSelector: &RoleAssignment_RolePriority{ + RolePriority: &RolePriority{ + Entries: []*RolePriorityEntry{ + {Role: &RolePriorityEntry_RegistryRole{RegistryRole: RegistryRole_REGISTRY_ROLE_CONTROLLER}}, + {Role: &RolePriorityEntry_NftRole{NftRole: NftRole_NFT_ROLE_NFT_OWNER}}, + }, + }, + }, + Assignment: Assignment_ASSIGNMENT_CURRENT, + }, + }, + }, + { + // The current Secured Party for eNote must sign (if set). + // The new/incoming controller must sign (if being assigned). + Type: SignatureType_SIGNATURE_TYPE_REQUIRED_ALL_IF_SET, + Roles: []*RoleAssignment{ + { + RoleSelector: &RoleAssignment_RegistryRole{RegistryRole: RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE}, + Assignment: Assignment_ASSIGNMENT_CURRENT, + }, + { + RoleSelector: &RoleAssignment_RegistryRole{RegistryRole: RegistryRole_REGISTRY_ROLE_CONTROLLER}, + Assignment: Assignment_ASSIGNMENT_NEW, + }, + }, + }, + }, + }, + }, + } +} diff --git a/x/registry/types/authorization.pb.go b/x/registry/types/authorization.pb.go new file mode 100644 index 0000000000..6e5f7c24fc --- /dev/null +++ b/x/registry/types/authorization.pb.go @@ -0,0 +1,2175 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: provenance/registry/v1/authorization.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/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 + +// SignatureType defines how signature requirements are evaluated. +type SignatureType int32 + +const ( + // SIGNATURE_TYPE_UNSPECIFIED is the default/unset value. + SignatureType_SIGNATURE_TYPE_UNSPECIFIED SignatureType = 0 + // SIGNATURE_TYPE_REQUIRED_ALL requires signatures from ALL listed roles. + // Fails immediately if any role does not exist in the registry or NFT state. + SignatureType_SIGNATURE_TYPE_REQUIRED_ALL SignatureType = 1 + // SIGNATURE_TYPE_REQUIRED_ALL_IF_SET requires signatures from ALL listed roles, + // but only if they exist. Roles that are not set are silently skipped. + SignatureType_SIGNATURE_TYPE_REQUIRED_ALL_IF_SET SignatureType = 2 + // SIGNATURE_TYPE_REQUIRED_ANY requires a signature from AT LEAST ONE of the listed roles. + // Fails if none of the roles exist. + SignatureType_SIGNATURE_TYPE_REQUIRED_ANY SignatureType = 3 + // SIGNATURE_TYPE_REQUIRED_ANY_IF_SET requires a signature from AT LEAST ONE of the listed roles, + // but only if any of them exist. Skips the entire requirement if none of the roles are set. + SignatureType_SIGNATURE_TYPE_REQUIRED_ANY_IF_SET SignatureType = 4 +) + +var SignatureType_name = map[int32]string{ + 0: "SIGNATURE_TYPE_UNSPECIFIED", + 1: "SIGNATURE_TYPE_REQUIRED_ALL", + 2: "SIGNATURE_TYPE_REQUIRED_ALL_IF_SET", + 3: "SIGNATURE_TYPE_REQUIRED_ANY", + 4: "SIGNATURE_TYPE_REQUIRED_ANY_IF_SET", +} + +var SignatureType_value = map[string]int32{ + "SIGNATURE_TYPE_UNSPECIFIED": 0, + "SIGNATURE_TYPE_REQUIRED_ALL": 1, + "SIGNATURE_TYPE_REQUIRED_ALL_IF_SET": 2, + "SIGNATURE_TYPE_REQUIRED_ANY": 3, + "SIGNATURE_TYPE_REQUIRED_ANY_IF_SET": 4, +} + +func (x SignatureType) String() string { + return proto.EnumName(SignatureType_name, int32(x)) +} + +func (SignatureType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{0} +} + +// NftRole identifies roles managed outside the registry module (e.g., by the metadata module). +// These roles are read-only from the registry module's perspective. +type NftRole int32 + +const ( + // NFT_ROLE_UNSPECIFIED is the default/unset value. + NftRole_NFT_ROLE_UNSPECIFIED NftRole = 0 + // NFT_ROLE_NFT_OWNER is the owner of the NFT. + // For metadata-scope NFTs, this is the scope value owner; otherwise it's the owner from the x/nft module. + NftRole_NFT_ROLE_NFT_OWNER NftRole = 1 +) + +var NftRole_name = map[int32]string{ + 0: "NFT_ROLE_UNSPECIFIED", + 1: "NFT_ROLE_NFT_OWNER", +} + +var NftRole_value = map[string]int32{ + "NFT_ROLE_UNSPECIFIED": 0, + "NFT_ROLE_NFT_OWNER": 1, +} + +func (x NftRole) String() string { + return proto.EnumName(NftRole_name, int32(x)) +} + +func (NftRole) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{1} +} + +// Assignment describes which address(es) to resolve for a role in an authorization check. +type Assignment int32 + +const ( + // ASSIGNMENT_UNSPECIFIED is the default/unset value. + Assignment_ASSIGNMENT_UNSPECIFIED Assignment = 0 + // ASSIGNMENT_CURRENT resolves exactly one address currently assigned to the role. + // Fails if the role has multiple addresses assigned. + Assignment_ASSIGNMENT_CURRENT Assignment = 1 + // ASSIGNMENT_CURRENT_ALL resolves all addresses currently assigned to the role. + // All of them must sign. + Assignment_ASSIGNMENT_CURRENT_ALL Assignment = 2 + // ASSIGNMENT_CURRENT_ANY resolves any one of the addresses currently assigned to the role. + // At least one must sign. + Assignment_ASSIGNMENT_CURRENT_ANY Assignment = 3 + // ASSIGNMENT_NEW resolves exactly one new address being assigned to the role. + // Fails if multiple new addresses are provided. + // Invalid for NftRole (read-only from registry perspective). + Assignment_ASSIGNMENT_NEW Assignment = 4 + // ASSIGNMENT_NEW_ANY resolves any one of the new addresses being assigned to the role. + // Invalid for NftRole. + Assignment_ASSIGNMENT_NEW_ANY Assignment = 5 + // ASSIGNMENT_NEW_ALL resolves all new addresses being assigned to the role. + // All of them must sign. + // Invalid for NftRole. + Assignment_ASSIGNMENT_NEW_ALL Assignment = 6 +) + +var Assignment_name = map[int32]string{ + 0: "ASSIGNMENT_UNSPECIFIED", + 1: "ASSIGNMENT_CURRENT", + 2: "ASSIGNMENT_CURRENT_ALL", + 3: "ASSIGNMENT_CURRENT_ANY", + 4: "ASSIGNMENT_NEW", + 5: "ASSIGNMENT_NEW_ANY", + 6: "ASSIGNMENT_NEW_ALL", +} + +var Assignment_value = map[string]int32{ + "ASSIGNMENT_UNSPECIFIED": 0, + "ASSIGNMENT_CURRENT": 1, + "ASSIGNMENT_CURRENT_ALL": 2, + "ASSIGNMENT_CURRENT_ANY": 3, + "ASSIGNMENT_NEW": 4, + "ASSIGNMENT_NEW_ANY": 5, + "ASSIGNMENT_NEW_ALL": 6, +} + +func (x Assignment) String() string { + return proto.EnumName(Assignment_name, int32(x)) +} + +func (Assignment) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{2} +} + +// RegistryClass provides asset class-level authorization over role updates. +// It defines authorization rules for an entire NFT collection (asset class), allowing the +// maintainer to establish custom role update policies without requiring governance proposals. +type RegistryClass struct { + // registry_class_id is the unique identifier for this registry class (e.g. "loan-registry-v1"). + // It is required since NFT classes do not have an inherent owner, and must be unique across + // all registry classes. + RegistryClassId string `protobuf:"bytes,1,opt,name=registry_class_id,json=registryClassId,proto3" json:"registryClassId,omitempty"` + // asset_class_id is the Scope Specification ID or NFT Class ID this registry class governs. + AssetClassId string `protobuf:"bytes,2,opt,name=asset_class_id,json=assetClassId,proto3" json:"asset_class_id,omitempty"` + // maintainer is the address authorized to manage this registry class. It is permanent and + // cannot be changed once set. + Maintainer string `protobuf:"bytes,3,opt,name=maintainer,proto3" json:"maintainer,omitempty"` + // role_authorizations are the authorization rules for role updates within this asset class. + RoleAuthorizations []RoleAuthorization `protobuf:"bytes,4,rep,name=role_authorizations,json=roleAuthorizations,proto3" json:"role_authorizations"` +} + +func (m *RegistryClass) Reset() { *m = RegistryClass{} } +func (m *RegistryClass) String() string { return proto.CompactTextString(m) } +func (*RegistryClass) ProtoMessage() {} +func (*RegistryClass) Descriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{0} +} +func (m *RegistryClass) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RegistryClass) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RegistryClass.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 *RegistryClass) XXX_Merge(src proto.Message) { + xxx_messageInfo_RegistryClass.Merge(m, src) +} +func (m *RegistryClass) XXX_Size() int { + return m.Size() +} +func (m *RegistryClass) XXX_DiscardUnknown() { + xxx_messageInfo_RegistryClass.DiscardUnknown(m) +} + +var xxx_messageInfo_RegistryClass proto.InternalMessageInfo + +func (m *RegistryClass) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId + } + return "" +} + +func (m *RegistryClass) GetAssetClassId() string { + if m != nil { + return m.AssetClassId + } + return "" +} + +func (m *RegistryClass) GetMaintainer() string { + if m != nil { + return m.Maintainer + } + return "" +} + +func (m *RegistryClass) GetRoleAuthorizations() []RoleAuthorization { + if m != nil { + return m.RoleAuthorizations + } + return nil +} + +// RoleAuthorization configures who must sign to update a specific role. +// Contains one or more Authorization paths; the update is approved if ANY path is fully satisfied. +type RoleAuthorization struct { + // role is the registry role whose assignments are being controlled. + Role RegistryRole `protobuf:"varint,1,opt,name=role,proto3,enum=provenance.registry.v1.RegistryRole" json:"role,omitempty"` + // authorizations is a list of alternative approval paths. + // The role update is approved if any single authorization is fully satisfied. + Authorizations []*Authorization `protobuf:"bytes,2,rep,name=authorizations,proto3" json:"authorizations,omitempty"` +} + +func (m *RoleAuthorization) Reset() { *m = RoleAuthorization{} } +func (m *RoleAuthorization) String() string { return proto.CompactTextString(m) } +func (*RoleAuthorization) ProtoMessage() {} +func (*RoleAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{1} +} +func (m *RoleAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RoleAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RoleAuthorization.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 *RoleAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_RoleAuthorization.Merge(m, src) +} +func (m *RoleAuthorization) XXX_Size() int { + return m.Size() +} +func (m *RoleAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_RoleAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_RoleAuthorization proto.InternalMessageInfo + +func (m *RoleAuthorization) GetRole() RegistryRole { + if m != nil { + return m.Role + } + return RegistryRole_REGISTRY_ROLE_UNSPECIFIED +} + +func (m *RoleAuthorization) GetAuthorizations() []*Authorization { + if m != nil { + return m.Authorizations + } + return nil +} + +// Authorization defines one complete approval path for a role update. +// All signature requirements in this authorization must be satisfied for this path to succeed. +type Authorization struct { + // description is a human-readable explanation of this authorization path. + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + // signatures is the ordered list of signature requirements that must all be satisfied. + Signatures []*SignatureRequirement `protobuf:"bytes,2,rep,name=signatures,proto3" json:"signatures,omitempty"` +} + +func (m *Authorization) Reset() { *m = Authorization{} } +func (m *Authorization) String() string { return proto.CompactTextString(m) } +func (*Authorization) ProtoMessage() {} +func (*Authorization) Descriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{2} +} +func (m *Authorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Authorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Authorization.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 *Authorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_Authorization.Merge(m, src) +} +func (m *Authorization) XXX_Size() int { + return m.Size() +} +func (m *Authorization) XXX_DiscardUnknown() { + xxx_messageInfo_Authorization.DiscardUnknown(m) +} + +var xxx_messageInfo_Authorization proto.InternalMessageInfo + +func (m *Authorization) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *Authorization) GetSignatures() []*SignatureRequirement { + if m != nil { + return m.Signatures + } + return nil +} + +// SignatureRequirement defines a single signature check within an authorization path. +type SignatureRequirement struct { + // type controls how the roles are evaluated (required_all, required_all_if_set, etc.). + Type SignatureType `protobuf:"varint,1,opt,name=type,proto3,enum=provenance.registry.v1.SignatureType" json:"type,omitempty"` + // roles lists the role assignments that must be checked. + Roles []*RoleAssignment `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"` +} + +func (m *SignatureRequirement) Reset() { *m = SignatureRequirement{} } +func (m *SignatureRequirement) String() string { return proto.CompactTextString(m) } +func (*SignatureRequirement) ProtoMessage() {} +func (*SignatureRequirement) Descriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{3} +} +func (m *SignatureRequirement) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignatureRequirement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignatureRequirement.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 *SignatureRequirement) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignatureRequirement.Merge(m, src) +} +func (m *SignatureRequirement) XXX_Size() int { + return m.Size() +} +func (m *SignatureRequirement) XXX_DiscardUnknown() { + xxx_messageInfo_SignatureRequirement.DiscardUnknown(m) +} + +var xxx_messageInfo_SignatureRequirement proto.InternalMessageInfo + +func (m *SignatureRequirement) GetType() SignatureType { + if m != nil { + return m.Type + } + return SignatureType_SIGNATURE_TYPE_UNSPECIFIED +} + +func (m *SignatureRequirement) GetRoles() []*RoleAssignment { + if m != nil { + return m.Roles + } + return nil +} + +// RoleAssignment specifies which role and which assignment type to resolve for a signature check. +type RoleAssignment struct { + // role_selector identifies the role to resolve, either a single role or a priority list. + // + // Types that are valid to be assigned to RoleSelector: + // + // *RoleAssignment_RegistryRole + // *RoleAssignment_NftRole + // *RoleAssignment_RolePriority + RoleSelector isRoleAssignment_RoleSelector `protobuf_oneof:"role_selector"` + // assignment specifies which address(es) to resolve for the role. + Assignment Assignment `protobuf:"varint,4,opt,name=assignment,proto3,enum=provenance.registry.v1.Assignment" json:"assignment,omitempty"` +} + +func (m *RoleAssignment) Reset() { *m = RoleAssignment{} } +func (m *RoleAssignment) String() string { return proto.CompactTextString(m) } +func (*RoleAssignment) ProtoMessage() {} +func (*RoleAssignment) Descriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{4} +} +func (m *RoleAssignment) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RoleAssignment) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RoleAssignment.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 *RoleAssignment) XXX_Merge(src proto.Message) { + xxx_messageInfo_RoleAssignment.Merge(m, src) +} +func (m *RoleAssignment) XXX_Size() int { + return m.Size() +} +func (m *RoleAssignment) XXX_DiscardUnknown() { + xxx_messageInfo_RoleAssignment.DiscardUnknown(m) +} + +var xxx_messageInfo_RoleAssignment proto.InternalMessageInfo + +type isRoleAssignment_RoleSelector interface { + isRoleAssignment_RoleSelector() + MarshalTo([]byte) (int, error) + Size() int +} + +type RoleAssignment_RegistryRole struct { + RegistryRole RegistryRole `protobuf:"varint,1,opt,name=registry_role,json=registryRole,proto3,enum=provenance.registry.v1.RegistryRole,oneof" json:"registry_role,omitempty"` +} +type RoleAssignment_NftRole struct { + NftRole NftRole `protobuf:"varint,2,opt,name=nft_role,json=nftRole,proto3,enum=provenance.registry.v1.NftRole,oneof" json:"nft_role,omitempty"` +} +type RoleAssignment_RolePriority struct { + RolePriority *RolePriority `protobuf:"bytes,3,opt,name=role_priority,json=rolePriority,proto3,oneof" json:"role_priority,omitempty"` +} + +func (*RoleAssignment_RegistryRole) isRoleAssignment_RoleSelector() {} +func (*RoleAssignment_NftRole) isRoleAssignment_RoleSelector() {} +func (*RoleAssignment_RolePriority) isRoleAssignment_RoleSelector() {} + +func (m *RoleAssignment) GetRoleSelector() isRoleAssignment_RoleSelector { + if m != nil { + return m.RoleSelector + } + return nil +} + +func (m *RoleAssignment) GetRegistryRole() RegistryRole { + if x, ok := m.GetRoleSelector().(*RoleAssignment_RegistryRole); ok { + return x.RegistryRole + } + return RegistryRole_REGISTRY_ROLE_UNSPECIFIED +} + +func (m *RoleAssignment) GetNftRole() NftRole { + if x, ok := m.GetRoleSelector().(*RoleAssignment_NftRole); ok { + return x.NftRole + } + return NftRole_NFT_ROLE_UNSPECIFIED +} + +func (m *RoleAssignment) GetRolePriority() *RolePriority { + if x, ok := m.GetRoleSelector().(*RoleAssignment_RolePriority); ok { + return x.RolePriority + } + return nil +} + +func (m *RoleAssignment) GetAssignment() Assignment { + if m != nil { + return m.Assignment + } + return Assignment_ASSIGNMENT_UNSPECIFIED +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*RoleAssignment) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*RoleAssignment_RegistryRole)(nil), + (*RoleAssignment_NftRole)(nil), + (*RoleAssignment_RolePriority)(nil), + } +} + +// RolePriority is an ordered list of role entries used for fallback/hierarchical authority. +// The keeper uses the first role in the list that exists. +type RolePriority struct { + // entries is the ordered list of roles to check. The first existing role is used. + Entries []*RolePriorityEntry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"` +} + +func (m *RolePriority) Reset() { *m = RolePriority{} } +func (m *RolePriority) String() string { return proto.CompactTextString(m) } +func (*RolePriority) ProtoMessage() {} +func (*RolePriority) Descriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{5} +} +func (m *RolePriority) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RolePriority) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RolePriority.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 *RolePriority) XXX_Merge(src proto.Message) { + xxx_messageInfo_RolePriority.Merge(m, src) +} +func (m *RolePriority) XXX_Size() int { + return m.Size() +} +func (m *RolePriority) XXX_DiscardUnknown() { + xxx_messageInfo_RolePriority.DiscardUnknown(m) +} + +var xxx_messageInfo_RolePriority proto.InternalMessageInfo + +func (m *RolePriority) GetEntries() []*RolePriorityEntry { + if m != nil { + return m.Entries + } + return nil +} + +// RolePriorityEntry is a single entry in a RolePriority list. +type RolePriorityEntry struct { + // role identifies the role in this priority slot. + // + // Types that are valid to be assigned to Role: + // + // *RolePriorityEntry_RegistryRole + // *RolePriorityEntry_NftRole + Role isRolePriorityEntry_Role `protobuf_oneof:"role"` +} + +func (m *RolePriorityEntry) Reset() { *m = RolePriorityEntry{} } +func (m *RolePriorityEntry) String() string { return proto.CompactTextString(m) } +func (*RolePriorityEntry) ProtoMessage() {} +func (*RolePriorityEntry) Descriptor() ([]byte, []int) { + return fileDescriptor_3c5d2a6c632d9975, []int{6} +} +func (m *RolePriorityEntry) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RolePriorityEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RolePriorityEntry.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 *RolePriorityEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_RolePriorityEntry.Merge(m, src) +} +func (m *RolePriorityEntry) XXX_Size() int { + return m.Size() +} +func (m *RolePriorityEntry) XXX_DiscardUnknown() { + xxx_messageInfo_RolePriorityEntry.DiscardUnknown(m) +} + +var xxx_messageInfo_RolePriorityEntry proto.InternalMessageInfo + +type isRolePriorityEntry_Role interface { + isRolePriorityEntry_Role() + MarshalTo([]byte) (int, error) + Size() int +} + +type RolePriorityEntry_RegistryRole struct { + RegistryRole RegistryRole `protobuf:"varint,1,opt,name=registry_role,json=registryRole,proto3,enum=provenance.registry.v1.RegistryRole,oneof" json:"registry_role,omitempty"` +} +type RolePriorityEntry_NftRole struct { + NftRole NftRole `protobuf:"varint,2,opt,name=nft_role,json=nftRole,proto3,enum=provenance.registry.v1.NftRole,oneof" json:"nft_role,omitempty"` +} + +func (*RolePriorityEntry_RegistryRole) isRolePriorityEntry_Role() {} +func (*RolePriorityEntry_NftRole) isRolePriorityEntry_Role() {} + +func (m *RolePriorityEntry) GetRole() isRolePriorityEntry_Role { + if m != nil { + return m.Role + } + return nil +} + +func (m *RolePriorityEntry) GetRegistryRole() RegistryRole { + if x, ok := m.GetRole().(*RolePriorityEntry_RegistryRole); ok { + return x.RegistryRole + } + return RegistryRole_REGISTRY_ROLE_UNSPECIFIED +} + +func (m *RolePriorityEntry) GetNftRole() NftRole { + if x, ok := m.GetRole().(*RolePriorityEntry_NftRole); ok { + return x.NftRole + } + return NftRole_NFT_ROLE_UNSPECIFIED +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*RolePriorityEntry) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*RolePriorityEntry_RegistryRole)(nil), + (*RolePriorityEntry_NftRole)(nil), + } +} + +func init() { + proto.RegisterEnum("provenance.registry.v1.SignatureType", SignatureType_name, SignatureType_value) + proto.RegisterEnum("provenance.registry.v1.NftRole", NftRole_name, NftRole_value) + proto.RegisterEnum("provenance.registry.v1.Assignment", Assignment_name, Assignment_value) + proto.RegisterType((*RegistryClass)(nil), "provenance.registry.v1.RegistryClass") + proto.RegisterType((*RoleAuthorization)(nil), "provenance.registry.v1.RoleAuthorization") + proto.RegisterType((*Authorization)(nil), "provenance.registry.v1.Authorization") + proto.RegisterType((*SignatureRequirement)(nil), "provenance.registry.v1.SignatureRequirement") + proto.RegisterType((*RoleAssignment)(nil), "provenance.registry.v1.RoleAssignment") + proto.RegisterType((*RolePriority)(nil), "provenance.registry.v1.RolePriority") + proto.RegisterType((*RolePriorityEntry)(nil), "provenance.registry.v1.RolePriorityEntry") +} + +func init() { + proto.RegisterFile("provenance/registry/v1/authorization.proto", fileDescriptor_3c5d2a6c632d9975) +} + +var fileDescriptor_3c5d2a6c632d9975 = []byte{ + // 797 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0x41, 0x6f, 0x1b, 0x45, + 0x14, 0xf6, 0x3a, 0x6e, 0x02, 0x2f, 0xb1, 0xbb, 0x1d, 0xac, 0xc8, 0x31, 0xc2, 0x8e, 0x56, 0x4d, + 0x55, 0xac, 0xd6, 0x56, 0x0b, 0x87, 0x22, 0x7a, 0xb1, 0xdd, 0x0d, 0x58, 0xb8, 0x5b, 0x33, 0xb6, + 0x15, 0x85, 0xcb, 0xb2, 0xb5, 0xa7, 0xee, 0x08, 0x7b, 0xc7, 0xcc, 0x8c, 0x23, 0xcc, 0x85, 0x9f, + 0x00, 0x3f, 0x20, 0x67, 0x7e, 0x01, 0x47, 0x38, 0x70, 0xcb, 0x31, 0xe2, 0xc4, 0x29, 0x42, 0xc9, + 0x8d, 0x5f, 0x81, 0x76, 0x76, 0xd7, 0x5e, 0x6f, 0xb2, 0x8e, 0xb8, 0xf5, 0x36, 0xf3, 0xbe, 0xef, + 0x7d, 0xef, 0x9b, 0x37, 0x6f, 0x76, 0xa1, 0x32, 0xe5, 0xec, 0x84, 0xb8, 0x8e, 0x3b, 0x20, 0x35, + 0x4e, 0x46, 0x54, 0x48, 0x3e, 0xaf, 0x9d, 0x3c, 0xa9, 0x39, 0x33, 0xf9, 0x96, 0x71, 0xfa, 0xa3, + 0x23, 0x29, 0x73, 0xab, 0x53, 0xce, 0x24, 0x43, 0xbb, 0x4b, 0x6e, 0x35, 0xe4, 0x56, 0x4f, 0x9e, + 0x14, 0xf3, 0x23, 0x36, 0x62, 0x8a, 0x52, 0xf3, 0x56, 0x3e, 0xbb, 0xb8, 0x37, 0x60, 0x62, 0xc2, + 0x84, 0xed, 0x03, 0xfe, 0x26, 0x80, 0x0e, 0x12, 0x8a, 0x2e, 0x44, 0x15, 0xcd, 0x38, 0x4d, 0x43, + 0x16, 0x07, 0xa1, 0xe6, 0xd8, 0x11, 0x02, 0xb5, 0xe0, 0x5e, 0xc8, 0xb1, 0x07, 0x5e, 0xc4, 0xa6, + 0xc3, 0x82, 0xb6, 0xaf, 0x3d, 0x7c, 0xbf, 0xf1, 0xd1, 0xbf, 0x17, 0xe5, 0x3d, 0x1e, 0x65, 0xb7, + 0x86, 0x8f, 0xd8, 0x84, 0x4a, 0x32, 0x99, 0xca, 0x39, 0xbe, 0x1b, 0x83, 0xd0, 0x7d, 0xc8, 0x39, + 0x42, 0x10, 0xb9, 0xd4, 0x49, 0x7b, 0x3a, 0x78, 0x47, 0x45, 0x43, 0xd6, 0x33, 0x80, 0x89, 0x43, + 0x5d, 0xe9, 0x50, 0x97, 0xf0, 0xc2, 0x86, 0xaa, 0x54, 0xf8, 0xeb, 0xb7, 0xc7, 0xf9, 0xe0, 0x3c, + 0xf5, 0xe1, 0x90, 0x13, 0x21, 0xba, 0x92, 0x53, 0x77, 0x84, 0x23, 0x5c, 0xf4, 0x2d, 0x7c, 0xc0, + 0xd9, 0x98, 0xd8, 0x2b, 0x8d, 0x14, 0x85, 0xcc, 0xfe, 0xc6, 0xc3, 0xed, 0xa7, 0x1f, 0x57, 0x6f, + 0x6e, 0x65, 0x15, 0xb3, 0x31, 0xa9, 0x47, 0x33, 0x1a, 0x99, 0xb3, 0x8b, 0x72, 0x0a, 0x23, 0x1e, + 0x07, 0x84, 0x71, 0xaa, 0xc1, 0xbd, 0x6b, 0x7c, 0xf4, 0x0c, 0x32, 0x1e, 0x57, 0x75, 0x25, 0xf7, + 0xf4, 0x7e, 0x62, 0xa1, 0x60, 0xed, 0x09, 0x60, 0x95, 0x81, 0x5e, 0x42, 0x2e, 0x66, 0x36, 0xad, + 0xcc, 0x1e, 0x24, 0x69, 0xac, 0x14, 0xc6, 0xb1, 0x64, 0xe3, 0x27, 0xc8, 0xae, 0x3a, 0xdb, 0x87, + 0xed, 0x21, 0x11, 0x03, 0x4e, 0xa7, 0xde, 0xd6, 0xbf, 0x36, 0x1c, 0x0d, 0xa1, 0x36, 0x80, 0xa0, + 0x23, 0xd7, 0x91, 0x33, 0x4e, 0xc2, 0xea, 0x8f, 0x92, 0xaa, 0x77, 0x43, 0x26, 0x26, 0xdf, 0xcf, + 0x28, 0x27, 0x13, 0xe2, 0x4a, 0x1c, 0xc9, 0x37, 0x7e, 0xd6, 0x20, 0x7f, 0x13, 0x09, 0x7d, 0x06, + 0x19, 0x39, 0x9f, 0x86, 0x2d, 0x3a, 0xb8, 0xb5, 0x40, 0x6f, 0x3e, 0x25, 0x58, 0xa5, 0xa0, 0xe7, + 0x70, 0xc7, 0xeb, 0x55, 0x68, 0xee, 0xc1, 0xda, 0x7b, 0x14, 0x9e, 0x19, 0x65, 0xcb, 0x4f, 0x32, + 0xfe, 0x48, 0x43, 0x6e, 0x15, 0x41, 0x5f, 0x41, 0x76, 0x31, 0xd1, 0xff, 0xf7, 0xde, 0xbe, 0x4c, + 0xe1, 0x1d, 0x1e, 0xd9, 0xa3, 0xe7, 0xf0, 0x9e, 0xfb, 0x46, 0xfa, 0x3a, 0x69, 0xa5, 0x53, 0x4e, + 0xd2, 0xb1, 0xde, 0xc8, 0x40, 0x62, 0xcb, 0xf5, 0x97, 0xca, 0x8a, 0x37, 0xb1, 0x53, 0x4e, 0x19, + 0xa7, 0x72, 0xae, 0xc6, 0x7d, 0x7b, 0x8d, 0x15, 0x36, 0x26, 0x9d, 0x80, 0xab, 0xac, 0x44, 0xf6, + 0xa8, 0x01, 0xe0, 0x2c, 0x4e, 0x59, 0xc8, 0x28, 0x33, 0x46, 0xe2, 0x20, 0x2d, 0x3b, 0x15, 0xc9, + 0x6a, 0xdc, 0x0d, 0x0c, 0x09, 0x32, 0x26, 0x03, 0xc9, 0xb8, 0xd1, 0x85, 0x9d, 0x68, 0x51, 0xd4, + 0x84, 0x2d, 0xe2, 0x4a, 0x4e, 0x89, 0x28, 0x68, 0xb7, 0xbf, 0xab, 0x30, 0xcd, 0x74, 0xbd, 0x7e, + 0x85, 0x99, 0xc6, 0xaf, 0xc1, 0x33, 0x5a, 0x81, 0xdf, 0xa1, 0x7b, 0x69, 0x6c, 0xfa, 0x2f, 0xba, + 0xf2, 0xa7, 0x06, 0xd9, 0x95, 0x99, 0x44, 0x25, 0x28, 0x76, 0x5b, 0x5f, 0x58, 0xf5, 0x5e, 0x1f, + 0x9b, 0x76, 0xef, 0xb8, 0x63, 0xda, 0x7d, 0xab, 0xdb, 0x31, 0x9b, 0xad, 0xc3, 0x96, 0xf9, 0x42, + 0x4f, 0xa1, 0x32, 0x7c, 0x18, 0xc3, 0xb1, 0xf9, 0x75, 0xbf, 0x85, 0xcd, 0x17, 0x76, 0xbd, 0xdd, + 0xd6, 0x35, 0xf4, 0x00, 0x8c, 0x35, 0x04, 0xbb, 0x75, 0x68, 0x77, 0xcd, 0x9e, 0x9e, 0x5e, 0x2b, + 0x64, 0x1d, 0xeb, 0x1b, 0x6b, 0x85, 0xac, 0xe3, 0x50, 0x28, 0x53, 0xf9, 0x1c, 0xb6, 0x82, 0x13, + 0xa2, 0x02, 0xe4, 0xad, 0xc3, 0x9e, 0x8d, 0x5f, 0xb5, 0xe3, 0xb6, 0x77, 0x01, 0x2d, 0x10, 0x6f, + 0xf1, 0xea, 0xc8, 0x32, 0xb1, 0xae, 0x55, 0x7e, 0xd7, 0x00, 0x22, 0x4f, 0xa7, 0x08, 0xbb, 0xf5, + 0xae, 0x57, 0xf5, 0xa5, 0x69, 0xf5, 0xae, 0x4b, 0x44, 0xb0, 0x66, 0x1f, 0x63, 0xd3, 0xea, 0xe9, + 0x5a, 0x2c, 0x27, 0x88, 0xab, 0x66, 0xa4, 0x93, 0x30, 0x75, 0x3e, 0x04, 0xb9, 0x08, 0x66, 0x99, + 0x47, 0x7a, 0x26, 0x56, 0xc3, 0x32, 0x8f, 0x14, 0xf7, 0xce, 0x4d, 0xf1, 0x76, 0x5b, 0xdf, 0x6c, + 0x7c, 0x77, 0x76, 0x59, 0xd2, 0xce, 0x2f, 0x4b, 0xda, 0x3f, 0x97, 0x25, 0xed, 0x97, 0xab, 0x52, + 0xea, 0xfc, 0xaa, 0x94, 0xfa, 0xfb, 0xaa, 0x94, 0x82, 0x3d, 0xca, 0x12, 0xe6, 0xa1, 0xa3, 0x7d, + 0xf3, 0xe9, 0x88, 0xca, 0xb7, 0xb3, 0xd7, 0xd5, 0x01, 0x9b, 0xd4, 0x96, 0xa4, 0xc7, 0x94, 0x45, + 0x76, 0xb5, 0x1f, 0x96, 0xff, 0x51, 0xef, 0x3b, 0x25, 0x5e, 0x6f, 0xaa, 0x5f, 0xe8, 0x27, 0xff, + 0x05, 0x00, 0x00, 0xff, 0xff, 0xe2, 0xc8, 0x9d, 0x42, 0xe0, 0x07, 0x00, 0x00, +} + +func (m *RegistryClass) 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 *RegistryClass) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RegistryClass) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RoleAuthorizations) > 0 { + for iNdEx := len(m.RoleAuthorizations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoleAuthorizations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthorization(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.Maintainer) > 0 { + i -= len(m.Maintainer) + copy(dAtA[i:], m.Maintainer) + i = encodeVarintAuthorization(dAtA, i, uint64(len(m.Maintainer))) + i-- + dAtA[i] = 0x1a + } + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintAuthorization(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintAuthorization(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RoleAuthorization) 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 *RoleAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoleAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Authorizations) > 0 { + for iNdEx := len(m.Authorizations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Authorizations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthorization(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Role != 0 { + i = encodeVarintAuthorization(dAtA, i, uint64(m.Role)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Authorization) 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 *Authorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Authorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signatures) > 0 { + for iNdEx := len(m.Signatures) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Signatures[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthorization(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintAuthorization(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SignatureRequirement) 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 *SignatureRequirement) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignatureRequirement) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Roles) > 0 { + for iNdEx := len(m.Roles) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Roles[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthorization(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Type != 0 { + i = encodeVarintAuthorization(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *RoleAssignment) 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 *RoleAssignment) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoleAssignment) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Assignment != 0 { + i = encodeVarintAuthorization(dAtA, i, uint64(m.Assignment)) + i-- + dAtA[i] = 0x20 + } + if m.RoleSelector != nil { + { + size := m.RoleSelector.Size() + i -= size + if _, err := m.RoleSelector.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *RoleAssignment_RegistryRole) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoleAssignment_RegistryRole) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + i = encodeVarintAuthorization(dAtA, i, uint64(m.RegistryRole)) + i-- + dAtA[i] = 0x8 + return len(dAtA) - i, nil +} +func (m *RoleAssignment_NftRole) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoleAssignment_NftRole) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + i = encodeVarintAuthorization(dAtA, i, uint64(m.NftRole)) + i-- + dAtA[i] = 0x10 + return len(dAtA) - i, nil +} +func (m *RoleAssignment_RolePriority) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoleAssignment_RolePriority) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.RolePriority != nil { + { + size, err := m.RolePriority.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthorization(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *RolePriority) 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 *RolePriority) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RolePriority) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Entries) > 0 { + for iNdEx := len(m.Entries) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Entries[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthorization(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *RolePriorityEntry) 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 *RolePriorityEntry) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RolePriorityEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Role != nil { + { + size := m.Role.Size() + i -= size + if _, err := m.Role.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *RolePriorityEntry_RegistryRole) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RolePriorityEntry_RegistryRole) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + i = encodeVarintAuthorization(dAtA, i, uint64(m.RegistryRole)) + i-- + dAtA[i] = 0x8 + return len(dAtA) - i, nil +} +func (m *RolePriorityEntry_NftRole) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RolePriorityEntry_NftRole) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + i = encodeVarintAuthorization(dAtA, i, uint64(m.NftRole)) + i-- + dAtA[i] = 0x10 + return len(dAtA) - i, nil +} +func encodeVarintAuthorization(dAtA []byte, offset int, v uint64) int { + offset -= sovAuthorization(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *RegistryClass) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovAuthorization(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovAuthorization(uint64(l)) + } + l = len(m.Maintainer) + if l > 0 { + n += 1 + l + sovAuthorization(uint64(l)) + } + if len(m.RoleAuthorizations) > 0 { + for _, e := range m.RoleAuthorizations { + l = e.Size() + n += 1 + l + sovAuthorization(uint64(l)) + } + } + return n +} + +func (m *RoleAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Role != 0 { + n += 1 + sovAuthorization(uint64(m.Role)) + } + if len(m.Authorizations) > 0 { + for _, e := range m.Authorizations { + l = e.Size() + n += 1 + l + sovAuthorization(uint64(l)) + } + } + return n +} + +func (m *Authorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Description) + if l > 0 { + n += 1 + l + sovAuthorization(uint64(l)) + } + if len(m.Signatures) > 0 { + for _, e := range m.Signatures { + l = e.Size() + n += 1 + l + sovAuthorization(uint64(l)) + } + } + return n +} + +func (m *SignatureRequirement) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovAuthorization(uint64(m.Type)) + } + if len(m.Roles) > 0 { + for _, e := range m.Roles { + l = e.Size() + n += 1 + l + sovAuthorization(uint64(l)) + } + } + return n +} + +func (m *RoleAssignment) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.RoleSelector != nil { + n += m.RoleSelector.Size() + } + if m.Assignment != 0 { + n += 1 + sovAuthorization(uint64(m.Assignment)) + } + return n +} + +func (m *RoleAssignment_RegistryRole) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovAuthorization(uint64(m.RegistryRole)) + return n +} +func (m *RoleAssignment_NftRole) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovAuthorization(uint64(m.NftRole)) + return n +} +func (m *RoleAssignment_RolePriority) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.RolePriority != nil { + l = m.RolePriority.Size() + n += 1 + l + sovAuthorization(uint64(l)) + } + return n +} +func (m *RolePriority) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Entries) > 0 { + for _, e := range m.Entries { + l = e.Size() + n += 1 + l + sovAuthorization(uint64(l)) + } + } + return n +} + +func (m *RolePriorityEntry) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Role != nil { + n += m.Role.Size() + } + return n +} + +func (m *RolePriorityEntry_RegistryRole) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovAuthorization(uint64(m.RegistryRole)) + return n +} +func (m *RolePriorityEntry_NftRole) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovAuthorization(uint64(m.NftRole)) + return n +} + +func sovAuthorization(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAuthorization(x uint64) (n int) { + return sovAuthorization(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *RegistryClass) 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 ErrIntOverflowAuthorization + } + 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: RegistryClass: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RegistryClass: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + 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 ErrInvalidLengthAuthorization + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RegistryClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + 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 ErrInvalidLengthAuthorization + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Maintainer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + 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 ErrInvalidLengthAuthorization + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Maintainer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RoleAuthorizations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthorization + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RoleAuthorizations = append(m.RoleAuthorizations, RoleAuthorization{}) + if err := m.RoleAuthorizations[len(m.RoleAuthorizations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthorization(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthorization + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RoleAuthorization) 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 ErrIntOverflowAuthorization + } + 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: RoleAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RoleAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + } + m.Role = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Role |= RegistryRole(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorizations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthorization + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authorizations = append(m.Authorizations, &Authorization{}) + if err := m.Authorizations[len(m.Authorizations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthorization(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthorization + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Authorization) 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 ErrIntOverflowAuthorization + } + 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: Authorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Authorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowAuthorization + } + 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 ErrInvalidLengthAuthorization + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signatures", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthorization + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signatures = append(m.Signatures, &SignatureRequirement{}) + if err := m.Signatures[len(m.Signatures)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthorization(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthorization + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignatureRequirement) 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 ErrIntOverflowAuthorization + } + 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: SignatureRequirement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignatureRequirement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= SignatureType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Roles", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthorization + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Roles = append(m.Roles, &RoleAssignment{}) + if err := m.Roles[len(m.Roles)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthorization(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthorization + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RoleAssignment) 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 ErrIntOverflowAuthorization + } + 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: RoleAssignment: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RoleAssignment: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RegistryRole", wireType) + } + var v RegistryRole + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= RegistryRole(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.RoleSelector = &RoleAssignment_RegistryRole{v} + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NftRole", wireType) + } + var v NftRole + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= NftRole(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.RoleSelector = &RoleAssignment_NftRole{v} + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RolePriority", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthorization + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RolePriority{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.RoleSelector = &RoleAssignment_RolePriority{v} + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Assignment", wireType) + } + m.Assignment = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Assignment |= Assignment(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipAuthorization(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthorization + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RolePriority) 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 ErrIntOverflowAuthorization + } + 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: RolePriority: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RolePriority: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Entries", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthorization + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthorization + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Entries = append(m.Entries, &RolePriorityEntry{}) + if err := m.Entries[len(m.Entries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthorization(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthorization + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RolePriorityEntry) 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 ErrIntOverflowAuthorization + } + 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: RolePriorityEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RolePriorityEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RegistryRole", wireType) + } + var v RegistryRole + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= RegistryRole(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Role = &RolePriorityEntry_RegistryRole{v} + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NftRole", wireType) + } + var v NftRole + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthorization + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= NftRole(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Role = &RolePriorityEntry_NftRole{v} + default: + iNdEx = preIndex + skippy, err := skipAuthorization(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthorization + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAuthorization(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, ErrIntOverflowAuthorization + } + 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, ErrIntOverflowAuthorization + } + 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, ErrIntOverflowAuthorization + } + 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, ErrInvalidLengthAuthorization + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAuthorization + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAuthorization + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAuthorization = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAuthorization = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAuthorization = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/registry/types/authorization_test.go b/x/registry/types/authorization_test.go new file mode 100644 index 0000000000..1d1e0f345b --- /dev/null +++ b/x/registry/types/authorization_test.go @@ -0,0 +1,151 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/provenance-io/provenance/x/registry/types" +) + +func TestSignatureType_Validate(t *testing.T) { + tests := []struct { + name string + typ types.SignatureType + expErr string + }{ + {name: "required_all", typ: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL}, + {name: "required_any", typ: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ANY}, + {name: "unspecified", typ: types.SignatureType_SIGNATURE_TYPE_UNSPECIFIED, expErr: "cannot be unspecified"}, + {name: "undefined value", typ: types.SignatureType(9999), expErr: "unknown"}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.typ.Validate() + if tc.expErr == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErr) + } + }) + } +} + +func TestNftRole_Validate(t *testing.T) { + tests := []struct { + name string + role types.NftRole + expErr string + }{ + {name: "nft_owner", role: types.NftRole_NFT_ROLE_NFT_OWNER}, + {name: "unspecified", role: types.NftRole_NFT_ROLE_UNSPECIFIED, expErr: "cannot be unspecified"}, + {name: "undefined value", role: types.NftRole(9999), expErr: "unknown"}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.role.Validate() + if tc.expErr == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErr) + } + }) + } +} + +func TestAssignment_Validate(t *testing.T) { + tests := []struct { + name string + assignment types.Assignment + expErr string + }{ + {name: "current", assignment: types.Assignment_ASSIGNMENT_CURRENT}, + {name: "new", assignment: types.Assignment_ASSIGNMENT_NEW}, + {name: "unspecified", assignment: types.Assignment_ASSIGNMENT_UNSPECIFIED, expErr: "cannot be unspecified"}, + {name: "undefined value", assignment: types.Assignment(9999), expErr: "unknown"}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.assignment.Validate() + if tc.expErr == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErr) + } + }) + } +} + +func TestAssignment_IsCurrent(t *testing.T) { + currentVariants := []types.Assignment{ + types.Assignment_ASSIGNMENT_CURRENT, + types.Assignment_ASSIGNMENT_CURRENT_ALL, + types.Assignment_ASSIGNMENT_CURRENT_ANY, + } + for _, a := range currentVariants { + require.True(t, a.IsCurrent(), "%s should be current", a) + } + + nonCurrentVariants := []types.Assignment{ + types.Assignment_ASSIGNMENT_UNSPECIFIED, + types.Assignment_ASSIGNMENT_NEW, + types.Assignment_ASSIGNMENT_NEW_ALL, + types.Assignment_ASSIGNMENT_NEW_ANY, + } + for _, a := range nonCurrentVariants { + require.False(t, a.IsCurrent(), "%s should not be current", a) + } +} + +// TestControllerRoleAuthorizations confirms the shipped example CONTROLLER policy is well-formed: +// it is the fixture governance can install via params or a maintainer can adopt for a class, so it +// must pass the same validation any on-chain class policy must pass. +func TestControllerRoleAuthorizations(t *testing.T) { + auths := types.ControllerRoleAuthorizations() + require.Len(t, auths, 1) + require.Equal(t, types.RegistryRole_REGISTRY_ROLE_CONTROLLER, auths[0].Role) + + // Validate it via the same path a registry class uses. + errs := validateAuthsViaClass(t, auths) + require.NoError(t, errs) +} + +// validateAuthsViaClass runs the given role authorizations through RegistryClass.Validate so the +// example policy is exercised by the production validation code. +func validateAuthsViaClass(t *testing.T, auths []types.RoleAuthorization) error { + t.Helper() + c := validRegistryClass() + c.RoleAuthorizations = auths + return c.Validate() +} + +func TestRoleAuthorizationMapFrom(t *testing.T) { + t.Run("empty", func(t *testing.T) { + m := types.RoleAuthorizationMapFrom(nil) + require.Empty(t, m) + }) + + t.Run("indexed by role", func(t *testing.T) { + auths := []types.RoleAuthorization{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER}, + {Role: types.RegistryRole_REGISTRY_ROLE_SERVICER}, + } + m := types.RoleAuthorizationMapFrom(auths) + require.Len(t, m, 2) + require.Contains(t, m, types.RegistryRole_REGISTRY_ROLE_CONTROLLER) + require.Contains(t, m, types.RegistryRole_REGISTRY_ROLE_SERVICER) + }) + + t.Run("last entry wins on duplicate role", func(t *testing.T) { + auths := []types.RoleAuthorization{ + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Authorizations: []*types.Authorization{{Description: "first"}}}, + {Role: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, Authorizations: []*types.Authorization{{Description: "second"}}}, + } + m := types.RoleAuthorizationMapFrom(auths) + require.Len(t, m, 1) + require.Equal(t, "second", m[types.RegistryRole_REGISTRY_ROLE_CONTROLLER].Authorizations[0].Description) + }) +} diff --git a/x/registry/types/class.go b/x/registry/types/class.go new file mode 100644 index 0000000000..8b6dbdf179 --- /dev/null +++ b/x/registry/types/class.go @@ -0,0 +1,170 @@ +package types + +import ( + "errors" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// MaxLenRegistryClassID is the maximum length of a registry class id. +const MaxLenRegistryClassID = 128 + +// Validate validates the RegistryClass. +func (m *RegistryClass) Validate() error { + if m == nil { + return fmt.Errorf("registry class cannot be nil") + } + + var errs []error + if err := ValidateRegistryClassID(m.RegistryClassId); err != nil { + errs = append(errs, fmt.Errorf("registry_class_id: %w", err)) + } + + if err := ValidateClassID(m.AssetClassId); err != nil { + errs = append(errs, fmt.Errorf("asset_class_id: %w", err)) + } + + if _, err := sdk.AccAddressFromBech32(m.Maintainer); err != nil { + errs = append(errs, fmt.Errorf("maintainer: %w", err)) + } + + errs = append(errs, validateRoleAuthorizations(m.RoleAuthorizations)...) + + return errors.Join(errs...) +} + +// ValidateRegistryClassID validates the registry class id format. +func ValidateRegistryClassID(registryClassID string) error { + if err := ValidateStringLength(registryClassID, 1, MaxLenRegistryClassID); err != nil { + return err + } + if !alNumDashRx.MatchString(registryClassID) { + return fmt.Errorf("%q must only contain alphanumeric, '-', '.' characters", registryClassID) + } + return nil +} + +// validateRoleAuthorizations validates a set of role authorization policies. Each policy must +// reference a known, specified role, a role may be configured at most once, and every authorization +// path's signature requirements and role selectors must be well-formed. +func validateRoleAuthorizations(auths []RoleAuthorization) []error { + var errs []error + seen := make(map[RegistryRole]bool, len(auths)) + for i, auth := range auths { + if err := auth.Role.Validate(); err != nil { + errs = append(errs, NewErrCodeInvalidField("role_authorizations", "%d: role %s", i, err)) + } else if seen[auth.Role] { + errs = append(errs, NewErrCodeInvalidField("role_authorizations", "%d: duplicate role %s", i, auth.Role.ShortString())) + } else { + seen[auth.Role] = true + } + + if len(auth.Authorizations) == 0 { + errs = append(errs, NewErrCodeInvalidField("role_authorizations", "%d: at least one authorization path is required", i)) + } + for j, path := range auth.Authorizations { + errs = append(errs, validateAuthorizationPath(i, j, path)...) + } + } + return errs +} + +// validateAuthorizationPath validates a single authorization path (one of the "any path satisfies" +// alternatives) within a role authorization policy. i/j are the policy/path indices for error +// context. +func validateAuthorizationPath(i, j int, path *Authorization) []error { + var errs []error + if path == nil { + return []error{NewErrCodeInvalidField("role_authorizations", "%d: authorization %d is nil", i, j)} + } + if len(path.Signatures) == 0 { + errs = append(errs, NewErrCodeInvalidField("role_authorizations", "%d: authorization %d: at least one signature requirement is required", i, j)) + } + for k, req := range path.Signatures { + errs = append(errs, validateSignatureRequirement(i, j, k, req)...) + } + return errs +} + +// validateSignatureRequirement validates a single signature requirement: a known signature type and +// at least one well-formed role selector. i/j/k are the policy/path/requirement indices. +func validateSignatureRequirement(i, j, k int, req *SignatureRequirement) []error { + var errs []error + if req == nil { + return []error{NewErrCodeInvalidField("role_authorizations", "%d: authorization %d: signature %d is nil", i, j, k)} + } + if err := req.Type.Validate(); err != nil { + errs = append(errs, NewErrCodeInvalidField("role_authorizations", "%d: authorization %d: signature %d: type %s", i, j, k, err)) + } + if len(req.Roles) == 0 { + errs = append(errs, NewErrCodeInvalidField("role_authorizations", "%d: authorization %d: signature %d: at least one role selector is required", i, j, k)) + } + for l, ra := range req.Roles { + errs = append(errs, validateRoleAssignment(i, j, k, l, ra)...) + } + return errs +} + +// validateRoleAssignment validates a single role selector within a signature requirement. It +// enforces that exactly one selector kind is set, that referenced enum values are defined, and that +// NftRole selectors only use the CURRENT* assignment family. i/j/k/l are the nested indices. +func validateRoleAssignment(i, j, k, l int, ra *RoleAssignment) []error { + prefix := func(format string, args ...interface{}) error { + return NewErrCodeInvalidField("role_authorizations", + "%d: authorization %d: signature %d: role %d: "+format, append([]interface{}{i, j, k, l}, args...)...) + } + if ra == nil { + return []error{prefix("role selector is nil")} + } + + var errs []error + if err := ra.Assignment.Validate(); err != nil { + errs = append(errs, prefix("assignment %s", err)) + } + + switch r := ra.RoleSelector.(type) { + case *RoleAssignment_RegistryRole: + if err := r.RegistryRole.Validate(); err != nil { + errs = append(errs, prefix("registry_role %s", err)) + } + case *RoleAssignment_NftRole: + if err := r.NftRole.Validate(); err != nil { + errs = append(errs, prefix("nft_role %s", err)) + } else if !ra.Assignment.IsCurrent() { + errs = append(errs, prefix("nft_role may only be used with a CURRENT* assignment, got %s", ra.Assignment.String())) + } + case *RoleAssignment_RolePriority: + errs = append(errs, validateRolePriority(prefix, ra.Assignment, r.RolePriority)...) + default: + errs = append(errs, prefix("a role selector (registry_role, nft_role, or role_priority) must be set")) + } + return errs +} + +// validateRolePriority validates a role_priority fallback chain: it must contain at least one entry, +// and every entry must set exactly one selector with a defined enum value. NftRole entries inherit +// the assignment's CURRENT* constraint. +func validateRolePriority(prefix func(string, ...interface{}) error, assignment Assignment, rp *RolePriority) []error { + if rp == nil || len(rp.Entries) == 0 { + return []error{prefix("role_priority must contain at least one entry")} + } + var errs []error + for m, e := range rp.Entries { + switch r := e.Role.(type) { + case *RolePriorityEntry_RegistryRole: + if err := r.RegistryRole.Validate(); err != nil { + errs = append(errs, prefix("role_priority entry %d: registry_role %s", m, err)) + } + case *RolePriorityEntry_NftRole: + if err := r.NftRole.Validate(); err != nil { + errs = append(errs, prefix("role_priority entry %d: nft_role %s", m, err)) + } else if !assignment.IsCurrent() { + errs = append(errs, prefix("role_priority entry %d: nft_role may only be used with a CURRENT* assignment, got %s", m, assignment.String())) + } + default: + errs = append(errs, prefix("role_priority entry %d: a role (registry_role or nft_role) must be set", m)) + } + } + return errs +} diff --git a/x/registry/types/class_test.go b/x/registry/types/class_test.go new file mode 100644 index 0000000000..f7783a9fb7 --- /dev/null +++ b/x/registry/types/class_test.go @@ -0,0 +1,326 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/provenance-io/provenance/x/registry/types" +) + +// validRoleAuthorization builds a minimal, well-formed SERVICER policy: a single authorization path +// requiring the current controller to sign. It is used as the valid baseline that the negative +// cases mutate. +func validRoleAuthorization() types.RoleAuthorization { + return types.RoleAuthorization{ + Role: types.RegistryRole_REGISTRY_ROLE_SERVICER, + Authorizations: []*types.Authorization{ + { + Description: "controller may manage servicers", + Signatures: []*types.SignatureRequirement{ + { + Type: types.SignatureType_SIGNATURE_TYPE_REQUIRED_ALL, + Roles: []*types.RoleAssignment{ + { + RoleSelector: &types.RoleAssignment_RegistryRole{ + RegistryRole: types.RegistryRole_REGISTRY_ROLE_CONTROLLER, + }, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + }, + }, + }, + }, + }, + }, + } +} + +// validRegistryClass returns a well-formed RegistryClass that each negative case mutates. +func validRegistryClass() *types.RegistryClass { + return &types.RegistryClass{ + RegistryClassId: "loan-registry-v1", + AssetClassId: "asset-class-1", + Maintainer: sdk.AccAddress("class_maintainer_addr_").String(), + RoleAuthorizations: []types.RoleAuthorization{validRoleAuthorization()}, + } +} + +func TestRegistryClass_Validate(t *testing.T) { + tests := []struct { + name string + mutate func(c *types.RegistryClass) + expErr string + }{ + { + name: "valid", + mutate: func(_ *types.RegistryClass) {}, + }, + { + name: "empty registry_class_id", + mutate: func(c *types.RegistryClass) { c.RegistryClassId = "" }, + expErr: "registry_class_id", + }, + { + name: "registry_class_id with illegal character", + mutate: func(c *types.RegistryClass) { c.RegistryClassId = "bad id!" }, + expErr: "alphanumeric", + }, + { + name: "empty asset_class_id", + mutate: func(c *types.RegistryClass) { c.AssetClassId = "" }, + expErr: "asset_class_id", + }, + { + name: "invalid maintainer", + mutate: func(c *types.RegistryClass) { c.Maintainer = "not-bech32" }, + expErr: "maintainer", + }, + { + name: "duplicate role", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations = []types.RoleAuthorization{validRoleAuthorization(), validRoleAuthorization()} + }, + expErr: "duplicate role", + }, + { + name: "unspecified role", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Role = types.RegistryRole_REGISTRY_ROLE_UNSPECIFIED + }, + expErr: "role", + }, + { + name: "no authorization paths", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations = nil + }, + expErr: "at least one authorization path is required", + }, + { + name: "nil authorization path", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations = []*types.Authorization{nil} + }, + expErr: "authorization 0 is nil", + }, + { + name: "no signature requirements", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures = nil + }, + expErr: "at least one signature requirement is required", + }, + { + name: "nil signature requirement", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures = []*types.SignatureRequirement{nil} + }, + expErr: "signature 0 is nil", + }, + { + name: "unspecified signature type", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Type = types.SignatureType_SIGNATURE_TYPE_UNSPECIFIED + }, + expErr: "type", + }, + { + name: "no role selectors", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles = nil + }, + expErr: "at least one role selector is required", + }, + { + name: "nil role selector", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles = []*types.RoleAssignment{nil} + }, + expErr: "role selector is nil", + }, + { + name: "unspecified assignment", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0].Assignment = types.Assignment_ASSIGNMENT_UNSPECIFIED + }, + expErr: "assignment", + }, + { + name: "unspecified registry_role selector", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0].RoleSelector = + &types.RoleAssignment_RegistryRole{RegistryRole: types.RegistryRole_REGISTRY_ROLE_UNSPECIFIED} + }, + expErr: "registry_role", + }, + { + name: "no role selector kind set", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0].RoleSelector = nil + }, + expErr: "a role selector (registry_role, nft_role, or role_priority) must be set", + }, + { + name: "valid nft_role with current assignment", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0] = &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_NftRole{NftRole: types.NftRole_NFT_ROLE_NFT_OWNER}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + } + }, + }, + { + name: "nft_role with non-current assignment", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0] = &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_NftRole{NftRole: types.NftRole_NFT_ROLE_NFT_OWNER}, + Assignment: types.Assignment_ASSIGNMENT_NEW, + } + }, + expErr: "nft_role may only be used with a CURRENT* assignment", + }, + { + name: "unspecified nft_role", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0] = &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_NftRole{NftRole: types.NftRole_NFT_ROLE_UNSPECIFIED}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + } + }, + expErr: "nft_role", + }, + { + name: "valid role_priority", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0] = &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RolePriority{RolePriority: &types.RolePriority{ + Entries: []*types.RolePriorityEntry{ + {Role: &types.RolePriorityEntry_RegistryRole{RegistryRole: types.RegistryRole_REGISTRY_ROLE_CONTROLLER}}, + {Role: &types.RolePriorityEntry_NftRole{NftRole: types.NftRole_NFT_ROLE_NFT_OWNER}}, + }, + }}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + } + }, + }, + { + name: "empty role_priority", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0] = &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RolePriority{RolePriority: &types.RolePriority{}}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + } + }, + expErr: "role_priority must contain at least one entry", + }, + { + name: "nil role_priority", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0] = &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RolePriority{RolePriority: nil}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + } + }, + expErr: "role_priority must contain at least one entry", + }, + { + name: "role_priority entry with unspecified registry_role", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0] = &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RolePriority{RolePriority: &types.RolePriority{ + Entries: []*types.RolePriorityEntry{ + {Role: &types.RolePriorityEntry_RegistryRole{RegistryRole: types.RegistryRole_REGISTRY_ROLE_UNSPECIFIED}}, + }, + }}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + } + }, + expErr: "role_priority entry 0: registry_role", + }, + { + name: "role_priority entry nft_role with non-current assignment", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0] = &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RolePriority{RolePriority: &types.RolePriority{ + Entries: []*types.RolePriorityEntry{ + {Role: &types.RolePriorityEntry_NftRole{NftRole: types.NftRole_NFT_ROLE_NFT_OWNER}}, + }, + }}, + Assignment: types.Assignment_ASSIGNMENT_NEW, + } + }, + expErr: "role_priority entry 0: nft_role may only be used with a CURRENT* assignment", + }, + { + name: "role_priority entry with no role set", + mutate: func(c *types.RegistryClass) { + c.RoleAuthorizations[0].Authorizations[0].Signatures[0].Roles[0] = &types.RoleAssignment{ + RoleSelector: &types.RoleAssignment_RolePriority{RolePriority: &types.RolePriority{ + Entries: []*types.RolePriorityEntry{{}}, + }}, + Assignment: types.Assignment_ASSIGNMENT_CURRENT, + } + }, + expErr: "role_priority entry 0: a role (registry_role or nft_role) must be set", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + c := validRegistryClass() + tc.mutate(c) + err := c.Validate() + if tc.expErr == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErr) + } + }) + } +} + +func TestRegistryClass_Validate_Nil(t *testing.T) { + var c *types.RegistryClass + err := c.Validate() + require.Error(t, err) + require.Contains(t, err.Error(), "registry class cannot be nil") +} + +func TestValidateRegistryClassID(t *testing.T) { + tests := []struct { + name string + classID string + expErr string + }{ + {name: "valid alphanumeric", classID: "loan-registry-v1"}, + {name: "valid with dots", classID: "a.b.c"}, + {name: "empty", classID: "", expErr: "must be between"}, + {name: "illegal character", classID: "has space", expErr: "alphanumeric"}, + {name: "underscore not allowed", classID: "a_b", expErr: "alphanumeric"}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := types.ValidateRegistryClassID(tc.classID) + if tc.expErr == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErr) + } + }) + } +} + +func TestValidateRegistryClassID_TooLong(t *testing.T) { + id := make([]byte, types.MaxLenRegistryClassID+1) + for i := range id { + id[i] = 'a' + } + err := types.ValidateRegistryClassID(string(id)) + require.Error(t, err) + require.Contains(t, err.Error(), "must be between") +} diff --git a/x/registry/types/errors.go b/x/registry/types/errors.go index e3c307aa18..35983c7806 100644 --- a/x/registry/types/errors.go +++ b/x/registry/types/errors.go @@ -29,27 +29,35 @@ import ( type ErrCode string const ( - ErrCodeRegistryAlreadyExists ErrCode = "REGISTRY_ALREADY_EXISTS" - ErrCodeNFTNotFound ErrCode = "NFT_NOT_FOUND" - ErrCodeUnauthorized ErrCode = "UNAUTHORIZED" - ErrCodeInvalidRole ErrCode = "INVALID_ROLE" - ErrCodeRegistryNotFound ErrCode = "REGISTRY_NOT_FOUND" - ErrCodeAddressAlreadyHasRole ErrCode = "ADDRESS_ALREADY_HAS_ROLE" - ErrCodeInvalidKey ErrCode = "INVALID_KEY" - ErrCodeAddressDoesNotHaveRole ErrCode = "ADDRESS_DOES_NOT_HAVE_ROLE" - ErrCodeInvalidField ErrCode = "INVALID_FIELD" + ErrCodeRegistryAlreadyExists ErrCode = "REGISTRY_ALREADY_EXISTS" + ErrCodeNFTNotFound ErrCode = "NFT_NOT_FOUND" + ErrCodeUnauthorized ErrCode = "UNAUTHORIZED" + ErrCodeInvalidRole ErrCode = "INVALID_ROLE" + ErrCodeRegistryNotFound ErrCode = "REGISTRY_NOT_FOUND" + ErrCodeAddressAlreadyHasRole ErrCode = "ADDRESS_ALREADY_HAS_ROLE" + ErrCodeInvalidKey ErrCode = "INVALID_KEY" + ErrCodeAddressDoesNotHaveRole ErrCode = "ADDRESS_DOES_NOT_HAVE_ROLE" + ErrCodeInvalidField ErrCode = "INVALID_FIELD" + ErrCodePendingChangeNotFound ErrCode = "PENDING_CHANGE_NOT_FOUND" + ErrCodeRegistryClassExists ErrCode = "REGISTRY_CLASS_ALREADY_EXISTS" + ErrCodeRegistryClassNotFound ErrCode = "REGISTRY_CLASS_NOT_FOUND" + ErrCodeRegistryClassAssetMismatch ErrCode = "REGISTRY_CLASS_ASSET_MISMATCH" ) var ( - ErrRegistryAlreadyExists = cerrs.Register(ModuleName, 1, "registry already exists") - ErrNFTNotFound = cerrs.Register(ModuleName, 2, "NFT does not exist") - ErrUnauthorized = cerrs.Register(ModuleName, 3, "unauthorized") - ErrInvalidRole = cerrs.Register(ModuleName, 4, "invalid role") - ErrRegistryNotFound = cerrs.Register(ModuleName, 5, "registry not found") - ErrAddressAlreadyHasRole = cerrs.Register(ModuleName, 6, "address already has role") - ErrInvalidKey = cerrs.Register(ModuleName, 7, "invalid key") - ErrAddressDoesNotHaveRole = cerrs.Register(ModuleName, 8, "address does not have role") - ErrInvalidField = cerrs.Register(ModuleName, 9, "invalid field") + ErrRegistryAlreadyExists = cerrs.Register(ModuleName, 1, "registry already exists") + ErrNFTNotFound = cerrs.Register(ModuleName, 2, "NFT does not exist") + ErrUnauthorized = cerrs.Register(ModuleName, 3, "unauthorized") + ErrInvalidRole = cerrs.Register(ModuleName, 4, "invalid role") + ErrRegistryNotFound = cerrs.Register(ModuleName, 5, "registry not found") + ErrAddressAlreadyHasRole = cerrs.Register(ModuleName, 6, "address already has role") + ErrInvalidKey = cerrs.Register(ModuleName, 7, "invalid key") + ErrAddressDoesNotHaveRole = cerrs.Register(ModuleName, 8, "address does not have role") + ErrInvalidField = cerrs.Register(ModuleName, 9, "invalid field") + ErrPendingChangeNotFound = cerrs.Register(ModuleName, 10, "pending role change not found") + ErrRegistryClassExists = cerrs.Register(ModuleName, 11, "registry class already exists") + ErrRegistryClassNotFound = cerrs.Register(ModuleName, 12, "registry class not found") + ErrRegistryClassAssetMismatch = cerrs.Register(ModuleName, 13, "registry class asset class mismatch") ) func NewErrCodeRegistryAlreadyExists(key string) error { @@ -83,3 +91,25 @@ func NewErrCodeAddressDoesNotHaveRole(address, role string) error { func NewErrCodeInvalidField(field, format string, args ...interface{}) error { return cerrs.Wrapf(ErrInvalidField, "invalid %s: %s", field, fmt.Sprintf(format, args...)) } + +func NewErrCodePendingChangeNotFound(changeID string) error { + return cerrs.Wrapf(ErrPendingChangeNotFound, "pending role change not found: %q", changeID) +} + +func NewErrCodeRegistryClassExists(registryClassID string) error { + return cerrs.Wrapf(ErrRegistryClassExists, "registry class already exists: %q", registryClassID) +} + +func NewErrCodeRegistryClassNotFound(registryClassID string) error { + return cerrs.Wrapf(ErrRegistryClassNotFound, "registry class not found: %q", registryClassID) +} + +// NewErrCodeRegistryClassAssetMismatch reports that a registry entry references a registry class +// whose asset class id does not match the entry's asset class id. A registry class only governs +// entries within its own asset class, so applying it across collections would resolve authorization +// against the wrong policy tier. +func NewErrCodeRegistryClassAssetMismatch(registryClassID, classAssetClassID, entryAssetClassID string) error { + return cerrs.Wrapf(ErrRegistryClassAssetMismatch, + "registry class %q is for asset class %q, not %q", + registryClassID, classAssetClassID, entryAssetClassID) +} diff --git a/x/registry/types/events.go b/x/registry/types/events.go index 4baa0d01dc..9fb96bd081 100644 --- a/x/registry/types/events.go +++ b/x/registry/types/events.go @@ -49,6 +49,87 @@ func NewEventRegistryBulkUpdated(key *RegistryKey) *EventRegistryBulkUpdated { } } +// NewEventRoleChangeProposed returns a new EventRoleChangeProposed. +func NewEventRoleChangeProposed(change *PendingRoleChange) *EventRoleChangeProposed { + return &EventRoleChangeProposed{ + NftId: change.Key.NftId, + AssetClassId: change.Key.AssetClassId, + ChangeId: change.Id, + Proposer: change.Proposer, + } +} + +// NewEventRoleChangeApproved returns a new EventRoleChangeApproved. +func NewEventRoleChangeApproved(changeID, approver string) *EventRoleChangeApproved { + return &EventRoleChangeApproved{ + ChangeId: changeID, + Approver: approver, + } +} + +// NewEventRoleChangeApplied returns a new EventRoleChangeApplied. +func NewEventRoleChangeApplied(change *PendingRoleChange) *EventRoleChangeApplied { + return &EventRoleChangeApplied{ + NftId: change.Key.NftId, + AssetClassId: change.Key.AssetClassId, + ChangeId: change.Id, + } +} + +// NewEventRoleChangeCancelled returns a new EventRoleChangeCancelled. +func NewEventRoleChangeCancelled(changeID, cancelledBy string) *EventRoleChangeCancelled { + return &EventRoleChangeCancelled{ + ChangeId: changeID, + CancelledBy: cancelledBy, + } +} + +// NewEventRegistryClassCreated returns a new EventRegistryClassCreated. +func NewEventRegistryClassCreated(class *RegistryClass) *EventRegistryClassCreated { + return &EventRegistryClassCreated{ + RegistryClassId: class.RegistryClassId, + AssetClassId: class.AssetClassId, + Maintainer: class.Maintainer, + } +} + +// NewEventRegistryClassUpdated returns a new EventRegistryClassUpdated. +func NewEventRegistryClassUpdated(class *RegistryClass) *EventRegistryClassUpdated { + return &EventRegistryClassUpdated{ + RegistryClassId: class.RegistryClassId, + Maintainer: class.Maintainer, + } +} + +// NewEventParamsUpdated returns a new EventParamsUpdated. +func NewEventParamsUpdated() *EventParamsUpdated { + return &EventParamsUpdated{} +} + +// NewEventRoleUpdated returns a new EventRoleUpdated describing the full state transition for a +// single role, including the addresses before and after and the signers that authorized it. +func NewEventRoleUpdated(key *RegistryKey, registryClassID string, role RegistryRole, previousAddrs, currentAddrs []string, signers []RoleSigner) *EventRoleUpdated { + return &EventRoleUpdated{ + NftId: key.NftId, + AssetClassId: key.AssetClassId, + RegistryClassId: registryClassID, + Role: role.ShortString(), + Addresses: currentAddrs, + PreviousAddresses: previousAddrs, + Signers: signers, + } +} + +// NewNFTOwnerSigner returns the RoleSigner describing the legacy NFT-owner authorization path, where +// the NFT owner's signature alone authorizes a role change for a role with no configured policy. +func NewNFTOwnerSigner(owner string) RoleSigner { + return RoleSigner{ + Role: NftRole_NFT_ROLE_NFT_OWNER.String(), + Assignment: Assignment_ASSIGNMENT_CURRENT.String(), + Addresses: []string{owner}, + } +} + // GetChangeEvents gets all the events that represent the changes from oldReg to newReg. // Panics if they have different keys (unless oldReg or newReg is nil). func GetChangeEvents(oldReg, newReg *RegistryEntry) ([]*EventRoleGranted, []*EventRoleRevoked) { diff --git a/x/registry/types/events.pb.go b/x/registry/types/events.pb.go index 5c04924007..ec806f3547 100644 --- a/x/registry/types/events.pb.go +++ b/x/registry/types/events.pb.go @@ -5,6 +5,7 @@ package types import ( fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" math "math" @@ -319,381 +320,2954 @@ func (m *EventRegistryBulkUpdated) GetAssetClassId() string { return "" } -func init() { - proto.RegisterType((*EventNFTRegistered)(nil), "provenance.registry.v1.EventNFTRegistered") - proto.RegisterType((*EventRoleGranted)(nil), "provenance.registry.v1.EventRoleGranted") - proto.RegisterType((*EventRoleRevoked)(nil), "provenance.registry.v1.EventRoleRevoked") - proto.RegisterType((*EventNFTUnregistered)(nil), "provenance.registry.v1.EventNFTUnregistered") - proto.RegisterType((*EventRegistryBulkUpdated)(nil), "provenance.registry.v1.EventRegistryBulkUpdated") +// EventRoleChangeProposed is emitted when a pending role change is opened. +type EventRoleChangeProposed struct { + NftId string `protobuf:"bytes,1,opt,name=nft_id,json=nftId,proto3" json:"nft_id,omitempty"` + AssetClassId string `protobuf:"bytes,2,opt,name=asset_class_id,json=assetClassId,proto3" json:"asset_class_id,omitempty"` + ChangeId string `protobuf:"bytes,3,opt,name=change_id,json=changeId,proto3" json:"change_id,omitempty"` + Proposer string `protobuf:"bytes,4,opt,name=proposer,proto3" json:"proposer,omitempty"` } -func init() { - proto.RegisterFile("provenance/registry/v1/events.proto", fileDescriptor_61a0995529587ff0) +func (m *EventRoleChangeProposed) Reset() { *m = EventRoleChangeProposed{} } +func (m *EventRoleChangeProposed) String() string { return proto.CompactTextString(m) } +func (*EventRoleChangeProposed) ProtoMessage() {} +func (*EventRoleChangeProposed) Descriptor() ([]byte, []int) { + return fileDescriptor_61a0995529587ff0, []int{5} } - -var fileDescriptor_61a0995529587ff0 = []byte{ - // 304 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2e, 0x28, 0xca, 0x2f, - 0x4b, 0xcd, 0x4b, 0xcc, 0x4b, 0x4e, 0xd5, 0x2f, 0x4a, 0x4d, 0xcf, 0x2c, 0x2e, 0x29, 0xaa, 0xd4, - 0x2f, 0x33, 0xd4, 0x4f, 0x2d, 0x4b, 0xcd, 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, - 0x12, 0x43, 0x28, 0xd2, 0x83, 0x29, 0xd2, 0x2b, 0x33, 0x54, 0x0a, 0xe4, 0x12, 0x72, 0x05, 0xa9, - 0xf3, 0x73, 0x0b, 0x09, 0x02, 0x0b, 0xa7, 0x16, 0xa5, 0xa6, 0x08, 0x89, 0x72, 0xb1, 0xe5, 0xa5, - 0x95, 0xc4, 0x67, 0xa6, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xb1, 0xe6, 0xa5, 0x95, 0x78, - 0xa6, 0x08, 0xa9, 0x70, 0xf1, 0x25, 0x16, 0x17, 0xa7, 0x96, 0xc4, 0x27, 0xe7, 0x24, 0x16, 0x17, - 0x83, 0xa4, 0x99, 0xc0, 0xd2, 0x3c, 0x60, 0x51, 0x67, 0x90, 0xa0, 0x67, 0x8a, 0x52, 0x23, 0x23, - 0x97, 0x00, 0xd8, 0xcc, 0xa0, 0xfc, 0x9c, 0x54, 0xf7, 0xa2, 0xc4, 0xbc, 0x12, 0x0a, 0x4d, 0x14, - 0x12, 0xe2, 0x62, 0x29, 0xca, 0xcf, 0x49, 0x95, 0x60, 0x06, 0xcb, 0x81, 0xd9, 0x42, 0x32, 0x5c, - 0x9c, 0x89, 0x29, 0x29, 0x45, 0xa9, 0xc5, 0xc5, 0xa9, 0xc5, 0x12, 0x2c, 0x0a, 0xcc, 0x1a, 0x9c, - 0x41, 0x08, 0x01, 0x54, 0x37, 0x04, 0xa5, 0x96, 0xe5, 0x67, 0xd3, 0xdf, 0x0d, 0xc1, 0x5c, 0x22, - 0xb0, 0xa0, 0x0d, 0xcd, 0x2b, 0xa2, 0x52, 0xe0, 0x86, 0x73, 0x49, 0x40, 0xfc, 0x05, 0x8d, 0x43, - 0xa7, 0xd2, 0x9c, 0xec, 0xd0, 0x82, 0x94, 0x44, 0x4a, 0xc3, 0xd8, 0x29, 0xfb, 0xc4, 0x23, 0x39, - 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, - 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xb8, 0x24, 0x33, 0xf3, 0xf5, 0xb0, 0xa7, 0x9e, 0x00, 0xc6, - 0x28, 0x93, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x84, 0x22, 0xdd, - 0xcc, 0x7c, 0x24, 0x9e, 0x7e, 0x05, 0x22, 0x5d, 0x96, 0x54, 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, - 0x13, 0xa5, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x21, 0x15, 0x91, 0xbb, 0x02, 0x00, 0x00, +func (m *EventRoleChangeProposed) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) } - -func (m *EventNFTRegistered) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *EventRoleChangeProposed) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventRoleChangeProposed.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - return dAtA[:n], nil +} +func (m *EventRoleChangeProposed) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventRoleChangeProposed.Merge(m, src) +} +func (m *EventRoleChangeProposed) XXX_Size() int { + return m.Size() +} +func (m *EventRoleChangeProposed) XXX_DiscardUnknown() { + xxx_messageInfo_EventRoleChangeProposed.DiscardUnknown(m) } -func (m *EventNFTRegistered) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +var xxx_messageInfo_EventRoleChangeProposed proto.InternalMessageInfo + +func (m *EventRoleChangeProposed) GetNftId() string { + if m != nil { + return m.NftId + } + return "" } -func (m *EventNFTRegistered) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.AssetClassId) > 0 { - i -= len(m.AssetClassId) - copy(dAtA[i:], m.AssetClassId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) - i-- - dAtA[i] = 0x12 +func (m *EventRoleChangeProposed) GetAssetClassId() string { + if m != nil { + return m.AssetClassId } - if len(m.NftId) > 0 { - i -= len(m.NftId) - copy(dAtA[i:], m.NftId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) - i-- - dAtA[i] = 0xa + return "" +} + +func (m *EventRoleChangeProposed) GetChangeId() string { + if m != nil { + return m.ChangeId } - return len(dAtA) - i, nil + return "" } -func (m *EventRoleGranted) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *EventRoleChangeProposed) GetProposer() string { + if m != nil { + return m.Proposer } - return dAtA[:n], nil + return "" } -func (m *EventRoleGranted) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// EventRoleChangeApproved is emitted when a party records an approval for a pending role change. +type EventRoleChangeApproved struct { + ChangeId string `protobuf:"bytes,1,opt,name=change_id,json=changeId,proto3" json:"change_id,omitempty"` + Approver string `protobuf:"bytes,2,opt,name=approver,proto3" json:"approver,omitempty"` } -func (m *EventRoleGranted) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Addresses) > 0 { - for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Addresses[iNdEx]) - copy(dAtA[i:], m.Addresses[iNdEx]) - i = encodeVarintEvents(dAtA, i, uint64(len(m.Addresses[iNdEx]))) - i-- - dAtA[i] = 0x22 +func (m *EventRoleChangeApproved) Reset() { *m = EventRoleChangeApproved{} } +func (m *EventRoleChangeApproved) String() string { return proto.CompactTextString(m) } +func (*EventRoleChangeApproved) ProtoMessage() {} +func (*EventRoleChangeApproved) Descriptor() ([]byte, []int) { + return fileDescriptor_61a0995529587ff0, []int{6} +} +func (m *EventRoleChangeApproved) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventRoleChangeApproved) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventRoleChangeApproved.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - if len(m.Role) > 0 { - i -= len(m.Role) - copy(dAtA[i:], m.Role) - i = encodeVarintEvents(dAtA, i, uint64(len(m.Role))) - i-- - dAtA[i] = 0x1a - } - if len(m.AssetClassId) > 0 { - i -= len(m.AssetClassId) - copy(dAtA[i:], m.AssetClassId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) - i-- - dAtA[i] = 0x12 - } - if len(m.NftId) > 0 { - i -= len(m.NftId) - copy(dAtA[i:], m.NftId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) - i-- - dAtA[i] = 0xa +} +func (m *EventRoleChangeApproved) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventRoleChangeApproved.Merge(m, src) +} +func (m *EventRoleChangeApproved) XXX_Size() int { + return m.Size() +} +func (m *EventRoleChangeApproved) XXX_DiscardUnknown() { + xxx_messageInfo_EventRoleChangeApproved.DiscardUnknown(m) +} + +var xxx_messageInfo_EventRoleChangeApproved proto.InternalMessageInfo + +func (m *EventRoleChangeApproved) GetChangeId() string { + if m != nil { + return m.ChangeId } - return len(dAtA) - i, nil + return "" } -func (m *EventRoleRevoked) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *EventRoleChangeApproved) GetApprover() string { + if m != nil { + return m.Approver } - return dAtA[:n], nil + return "" } -func (m *EventRoleRevoked) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// EventRoleChangeApplied is emitted when a pending role change accumulates enough approvals and is applied. +type EventRoleChangeApplied struct { + NftId string `protobuf:"bytes,1,opt,name=nft_id,json=nftId,proto3" json:"nft_id,omitempty"` + AssetClassId string `protobuf:"bytes,2,opt,name=asset_class_id,json=assetClassId,proto3" json:"asset_class_id,omitempty"` + ChangeId string `protobuf:"bytes,3,opt,name=change_id,json=changeId,proto3" json:"change_id,omitempty"` } -func (m *EventRoleRevoked) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Addresses) > 0 { - for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Addresses[iNdEx]) - copy(dAtA[i:], m.Addresses[iNdEx]) - i = encodeVarintEvents(dAtA, i, uint64(len(m.Addresses[iNdEx]))) - i-- - dAtA[i] = 0x22 +func (m *EventRoleChangeApplied) Reset() { *m = EventRoleChangeApplied{} } +func (m *EventRoleChangeApplied) String() string { return proto.CompactTextString(m) } +func (*EventRoleChangeApplied) ProtoMessage() {} +func (*EventRoleChangeApplied) Descriptor() ([]byte, []int) { + return fileDescriptor_61a0995529587ff0, []int{7} +} +func (m *EventRoleChangeApplied) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventRoleChangeApplied) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventRoleChangeApplied.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - if len(m.Role) > 0 { - i -= len(m.Role) - copy(dAtA[i:], m.Role) - i = encodeVarintEvents(dAtA, i, uint64(len(m.Role))) - i-- - dAtA[i] = 0x1a - } - if len(m.AssetClassId) > 0 { - i -= len(m.AssetClassId) - copy(dAtA[i:], m.AssetClassId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) - i-- - dAtA[i] = 0x12 - } - if len(m.NftId) > 0 { - i -= len(m.NftId) - copy(dAtA[i:], m.NftId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil } - -func (m *EventNFTUnregistered) 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 *EventRoleChangeApplied) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventRoleChangeApplied.Merge(m, src) } - -func (m *EventNFTUnregistered) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +func (m *EventRoleChangeApplied) XXX_Size() int { + return m.Size() +} +func (m *EventRoleChangeApplied) XXX_DiscardUnknown() { + xxx_messageInfo_EventRoleChangeApplied.DiscardUnknown(m) } -func (m *EventNFTUnregistered) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.AssetClassId) > 0 { - i -= len(m.AssetClassId) - copy(dAtA[i:], m.AssetClassId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) - i-- - dAtA[i] = 0x12 +var xxx_messageInfo_EventRoleChangeApplied proto.InternalMessageInfo + +func (m *EventRoleChangeApplied) GetNftId() string { + if m != nil { + return m.NftId } - if len(m.NftId) > 0 { - i -= len(m.NftId) - copy(dAtA[i:], m.NftId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) - i-- - dAtA[i] = 0xa + return "" +} + +func (m *EventRoleChangeApplied) GetAssetClassId() string { + if m != nil { + return m.AssetClassId } - return len(dAtA) - i, nil + return "" } -func (m *EventRegistryBulkUpdated) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *EventRoleChangeApplied) GetChangeId() string { + if m != nil { + return m.ChangeId } - return dAtA[:n], nil + return "" } -func (m *EventRegistryBulkUpdated) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// EventRoleChangeCancelled is emitted when a pending role change is cancelled by its proposer. +type EventRoleChangeCancelled struct { + ChangeId string `protobuf:"bytes,1,opt,name=change_id,json=changeId,proto3" json:"change_id,omitempty"` + CancelledBy string `protobuf:"bytes,2,opt,name=cancelled_by,json=cancelledBy,proto3" json:"cancelled_by,omitempty"` } -func (m *EventRegistryBulkUpdated) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.AssetClassId) > 0 { - i -= len(m.AssetClassId) - copy(dAtA[i:], m.AssetClassId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) - i-- - dAtA[i] = 0x12 - } - if len(m.NftId) > 0 { - i -= len(m.NftId) - copy(dAtA[i:], m.NftId) - i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) - i-- - dAtA[i] = 0xa +func (m *EventRoleChangeCancelled) Reset() { *m = EventRoleChangeCancelled{} } +func (m *EventRoleChangeCancelled) String() string { return proto.CompactTextString(m) } +func (*EventRoleChangeCancelled) ProtoMessage() {} +func (*EventRoleChangeCancelled) Descriptor() ([]byte, []int) { + return fileDescriptor_61a0995529587ff0, []int{8} +} +func (m *EventRoleChangeCancelled) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventRoleChangeCancelled) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventRoleChangeCancelled.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - return len(dAtA) - i, nil +} +func (m *EventRoleChangeCancelled) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventRoleChangeCancelled.Merge(m, src) +} +func (m *EventRoleChangeCancelled) XXX_Size() int { + return m.Size() +} +func (m *EventRoleChangeCancelled) XXX_DiscardUnknown() { + xxx_messageInfo_EventRoleChangeCancelled.DiscardUnknown(m) } -func encodeVarintEvents(dAtA []byte, offset int, v uint64) int { - offset -= sovEvents(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ +var xxx_messageInfo_EventRoleChangeCancelled proto.InternalMessageInfo + +func (m *EventRoleChangeCancelled) GetChangeId() string { + if m != nil { + return m.ChangeId } - dAtA[offset] = uint8(v) - return base + return "" } -func (m *EventNFTRegistered) Size() (n int) { - if m == nil { - return 0 + +func (m *EventRoleChangeCancelled) GetCancelledBy() string { + if m != nil { + return m.CancelledBy } - var l int - _ = l - l = len(m.NftId) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) + return "" +} + +// EventRegistryClassCreated is emitted when a registry class is created. +type EventRegistryClassCreated struct { + RegistryClassId string `protobuf:"bytes,1,opt,name=registry_class_id,json=registryClassId,proto3" json:"registry_class_id,omitempty"` + AssetClassId string `protobuf:"bytes,2,opt,name=asset_class_id,json=assetClassId,proto3" json:"asset_class_id,omitempty"` + Maintainer string `protobuf:"bytes,3,opt,name=maintainer,proto3" json:"maintainer,omitempty"` +} + +func (m *EventRegistryClassCreated) Reset() { *m = EventRegistryClassCreated{} } +func (m *EventRegistryClassCreated) String() string { return proto.CompactTextString(m) } +func (*EventRegistryClassCreated) ProtoMessage() {} +func (*EventRegistryClassCreated) Descriptor() ([]byte, []int) { + return fileDescriptor_61a0995529587ff0, []int{9} +} +func (m *EventRegistryClassCreated) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventRegistryClassCreated) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventRegistryClassCreated.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - l = len(m.AssetClassId) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) +} +func (m *EventRegistryClassCreated) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventRegistryClassCreated.Merge(m, src) +} +func (m *EventRegistryClassCreated) XXX_Size() int { + return m.Size() +} +func (m *EventRegistryClassCreated) XXX_DiscardUnknown() { + xxx_messageInfo_EventRegistryClassCreated.DiscardUnknown(m) +} + +var xxx_messageInfo_EventRegistryClassCreated proto.InternalMessageInfo + +func (m *EventRegistryClassCreated) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId } - return n + return "" } -func (m *EventRoleGranted) Size() (n int) { - if m == nil { - return 0 +func (m *EventRegistryClassCreated) GetAssetClassId() string { + if m != nil { + return m.AssetClassId } - var l int - _ = l - l = len(m.NftId) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) + return "" +} + +func (m *EventRegistryClassCreated) GetMaintainer() string { + if m != nil { + return m.Maintainer } - l = len(m.AssetClassId) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) + return "" +} + +// EventRegistryClassUpdated is emitted when a registry class's authorization rules are updated. +type EventRegistryClassUpdated struct { + RegistryClassId string `protobuf:"bytes,1,opt,name=registry_class_id,json=registryClassId,proto3" json:"registry_class_id,omitempty"` + Maintainer string `protobuf:"bytes,2,opt,name=maintainer,proto3" json:"maintainer,omitempty"` +} + +func (m *EventRegistryClassUpdated) Reset() { *m = EventRegistryClassUpdated{} } +func (m *EventRegistryClassUpdated) String() string { return proto.CompactTextString(m) } +func (*EventRegistryClassUpdated) ProtoMessage() {} +func (*EventRegistryClassUpdated) Descriptor() ([]byte, []int) { + return fileDescriptor_61a0995529587ff0, []int{10} +} +func (m *EventRegistryClassUpdated) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventRegistryClassUpdated) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventRegistryClassUpdated.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - l = len(m.Role) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) +} +func (m *EventRegistryClassUpdated) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventRegistryClassUpdated.Merge(m, src) +} +func (m *EventRegistryClassUpdated) XXX_Size() int { + return m.Size() +} +func (m *EventRegistryClassUpdated) XXX_DiscardUnknown() { + xxx_messageInfo_EventRegistryClassUpdated.DiscardUnknown(m) +} + +var xxx_messageInfo_EventRegistryClassUpdated proto.InternalMessageInfo + +func (m *EventRegistryClassUpdated) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId } - if len(m.Addresses) > 0 { - for _, s := range m.Addresses { - l = len(s) - n += 1 + l + sovEvents(uint64(l)) + return "" +} + +func (m *EventRegistryClassUpdated) GetMaintainer() string { + if m != nil { + return m.Maintainer + } + return "" +} + +// EventParamsUpdated is emitted when the registry module's params are updated via governance. +type EventParamsUpdated struct { +} + +func (m *EventParamsUpdated) Reset() { *m = EventParamsUpdated{} } +func (m *EventParamsUpdated) String() string { return proto.CompactTextString(m) } +func (*EventParamsUpdated) ProtoMessage() {} +func (*EventParamsUpdated) Descriptor() ([]byte, []int) { + return fileDescriptor_61a0995529587ff0, []int{11} +} +func (m *EventParamsUpdated) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventParamsUpdated) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventParamsUpdated.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - return n +} +func (m *EventParamsUpdated) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventParamsUpdated.Merge(m, src) +} +func (m *EventParamsUpdated) XXX_Size() int { + return m.Size() +} +func (m *EventParamsUpdated) XXX_DiscardUnknown() { + xxx_messageInfo_EventParamsUpdated.DiscardUnknown(m) } -func (m *EventRoleRevoked) Size() (n int) { - if m == nil { - return 0 +var xxx_messageInfo_EventParamsUpdated proto.InternalMessageInfo + +// RoleSigner describes a role/assignment whose resolved addresses contributed a signature toward +// authorizing a role change. It is the structured form of an entry in EventRoleUpdated.signers. +type RoleSigner struct { + // role is the (registry or NFT) role whose holders provided the signature(s). + Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"` + // assignment is the assignment variant the role was resolved under (e.g. ASSIGNMENT_CURRENT). + Assignment string `protobuf:"bytes,2,opt,name=assignment,proto3" json:"assignment,omitempty"` + // addresses are the resolved addresses for the role that signed to authorize the change. + Addresses []string `protobuf:"bytes,3,rep,name=addresses,proto3" json:"addresses,omitempty"` +} + +func (m *RoleSigner) Reset() { *m = RoleSigner{} } +func (m *RoleSigner) String() string { return proto.CompactTextString(m) } +func (*RoleSigner) ProtoMessage() {} +func (*RoleSigner) Descriptor() ([]byte, []int) { + return fileDescriptor_61a0995529587ff0, []int{12} +} +func (m *RoleSigner) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RoleSigner) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RoleSigner.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - var l int - _ = l - l = len(m.NftId) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) +} +func (m *RoleSigner) XXX_Merge(src proto.Message) { + xxx_messageInfo_RoleSigner.Merge(m, src) +} +func (m *RoleSigner) XXX_Size() int { + return m.Size() +} +func (m *RoleSigner) XXX_DiscardUnknown() { + xxx_messageInfo_RoleSigner.DiscardUnknown(m) +} + +var xxx_messageInfo_RoleSigner proto.InternalMessageInfo + +func (m *RoleSigner) GetRole() string { + if m != nil { + return m.Role } - l = len(m.AssetClassId) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) + return "" +} + +func (m *RoleSigner) GetAssignment() string { + if m != nil { + return m.Assignment } - l = len(m.Role) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) + return "" +} + +func (m *RoleSigner) GetAddresses() []string { + if m != nil { + return m.Addresses } - if len(m.Addresses) > 0 { - for _, s := range m.Addresses { - l = len(s) - n += 1 + l + sovEvents(uint64(l)) + return nil +} + +// EventRoleUpdated is the comprehensive event emitted whenever a role is granted, revoked, or set +// for a registered NFT. It is emitted for MsgGrantRole, MsgRevokeRole, and once per updated role +// for MsgSetRoles (including changes applied via the propose/approve accumulation flow). +type EventRoleUpdated struct { + // nft_id is the ID of the NFT for which the role was updated. + NftId string `protobuf:"bytes,1,opt,name=nft_id,json=nftId,proto3" json:"nft_id,omitempty"` + // asset_class_id is the ID of the asset class the NFT belongs to. + AssetClassId string `protobuf:"bytes,2,opt,name=asset_class_id,json=assetClassId,proto3" json:"asset_class_id,omitempty"` + // registry_class_id is the registry class governing this NFT (empty if none). + RegistryClassId string `protobuf:"bytes,3,opt,name=registry_class_id,json=registryClassId,proto3" json:"registry_class_id,omitempty"` + // role is the role that was updated. + Role string `protobuf:"bytes,4,opt,name=role,proto3" json:"role,omitempty"` + // addresses are the addresses assigned to the role after this operation (empty if cleared). + Addresses []string `protobuf:"bytes,5,rep,name=addresses,proto3" json:"addresses,omitempty"` + // previous_addresses are the addresses assigned to the role before this operation. + PreviousAddresses []string `protobuf:"bytes,6,rep,name=previous_addresses,json=previousAddresses,proto3" json:"previous_addresses,omitempty"` + // signers describes the roles/addresses that authorized this change. + Signers []RoleSigner `protobuf:"bytes,7,rep,name=signers,proto3" json:"signers"` +} + +func (m *EventRoleUpdated) Reset() { *m = EventRoleUpdated{} } +func (m *EventRoleUpdated) String() string { return proto.CompactTextString(m) } +func (*EventRoleUpdated) ProtoMessage() {} +func (*EventRoleUpdated) Descriptor() ([]byte, []int) { + return fileDescriptor_61a0995529587ff0, []int{13} +} +func (m *EventRoleUpdated) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventRoleUpdated) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventRoleUpdated.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - return n +} +func (m *EventRoleUpdated) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventRoleUpdated.Merge(m, src) +} +func (m *EventRoleUpdated) XXX_Size() int { + return m.Size() +} +func (m *EventRoleUpdated) XXX_DiscardUnknown() { + xxx_messageInfo_EventRoleUpdated.DiscardUnknown(m) } -func (m *EventNFTUnregistered) Size() (n int) { - if m == nil { - return 0 +var xxx_messageInfo_EventRoleUpdated proto.InternalMessageInfo + +func (m *EventRoleUpdated) GetNftId() string { + if m != nil { + return m.NftId } - var l int - _ = l - l = len(m.NftId) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) + return "" +} + +func (m *EventRoleUpdated) GetAssetClassId() string { + if m != nil { + return m.AssetClassId } - l = len(m.AssetClassId) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) + return "" +} + +func (m *EventRoleUpdated) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId } - return n + return "" } -func (m *EventRegistryBulkUpdated) Size() (n int) { - if m == nil { - return 0 +func (m *EventRoleUpdated) GetRole() string { + if m != nil { + return m.Role } - var l int - _ = l - l = len(m.NftId) - if l > 0 { - n += 1 + l + sovEvents(uint64(l)) + return "" +} + +func (m *EventRoleUpdated) GetAddresses() []string { + if m != nil { + return m.Addresses } - l = len(m.AssetClassId) + return nil +} + +func (m *EventRoleUpdated) GetPreviousAddresses() []string { + if m != nil { + return m.PreviousAddresses + } + return nil +} + +func (m *EventRoleUpdated) GetSigners() []RoleSigner { + if m != nil { + return m.Signers + } + return nil +} + +func init() { + proto.RegisterType((*EventNFTRegistered)(nil), "provenance.registry.v1.EventNFTRegistered") + proto.RegisterType((*EventRoleGranted)(nil), "provenance.registry.v1.EventRoleGranted") + proto.RegisterType((*EventRoleRevoked)(nil), "provenance.registry.v1.EventRoleRevoked") + proto.RegisterType((*EventNFTUnregistered)(nil), "provenance.registry.v1.EventNFTUnregistered") + proto.RegisterType((*EventRegistryBulkUpdated)(nil), "provenance.registry.v1.EventRegistryBulkUpdated") + proto.RegisterType((*EventRoleChangeProposed)(nil), "provenance.registry.v1.EventRoleChangeProposed") + proto.RegisterType((*EventRoleChangeApproved)(nil), "provenance.registry.v1.EventRoleChangeApproved") + proto.RegisterType((*EventRoleChangeApplied)(nil), "provenance.registry.v1.EventRoleChangeApplied") + proto.RegisterType((*EventRoleChangeCancelled)(nil), "provenance.registry.v1.EventRoleChangeCancelled") + proto.RegisterType((*EventRegistryClassCreated)(nil), "provenance.registry.v1.EventRegistryClassCreated") + proto.RegisterType((*EventRegistryClassUpdated)(nil), "provenance.registry.v1.EventRegistryClassUpdated") + proto.RegisterType((*EventParamsUpdated)(nil), "provenance.registry.v1.EventParamsUpdated") + proto.RegisterType((*RoleSigner)(nil), "provenance.registry.v1.RoleSigner") + proto.RegisterType((*EventRoleUpdated)(nil), "provenance.registry.v1.EventRoleUpdated") +} + +func init() { + proto.RegisterFile("provenance/registry/v1/events.proto", fileDescriptor_61a0995529587ff0) +} + +var fileDescriptor_61a0995529587ff0 = []byte{ + // 597 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xdd, 0x6e, 0xd3, 0x30, + 0x14, 0x6e, 0xd6, 0xee, 0xa7, 0x67, 0x13, 0xb0, 0xa8, 0x8c, 0x6c, 0xa0, 0x50, 0x02, 0x17, 0x15, + 0xd2, 0x12, 0x0d, 0x78, 0x81, 0xb5, 0x02, 0xd4, 0x1b, 0x54, 0x32, 0x26, 0xa4, 0x5d, 0x50, 0xb9, + 0x8d, 0x97, 0x45, 0x4d, 0xed, 0xc8, 0x76, 0x23, 0x7a, 0xc9, 0x03, 0x20, 0x78, 0x04, 0x1e, 0x67, + 0x97, 0xbb, 0xe4, 0x0a, 0xa1, 0xf6, 0x45, 0x50, 0x9c, 0x3a, 0xe9, 0xdf, 0x04, 0xa8, 0x83, 0xbb, + 0xf8, 0x9c, 0xcf, 0xdf, 0xf9, 0xce, 0x17, 0x1f, 0x1b, 0x1e, 0x47, 0x8c, 0xc6, 0x98, 0x20, 0xd2, + 0xc5, 0x0e, 0xc3, 0x7e, 0xc0, 0x05, 0x1b, 0x3a, 0xf1, 0x91, 0x83, 0x63, 0x4c, 0x04, 0xb7, 0x23, + 0x46, 0x05, 0xd5, 0xf7, 0x72, 0x90, 0xad, 0x40, 0x76, 0x7c, 0x74, 0x50, 0xf1, 0xa9, 0x4f, 0x25, + 0xc4, 0x49, 0xbe, 0x52, 0xb4, 0xf5, 0x16, 0xf4, 0x97, 0xc9, 0xee, 0x37, 0xaf, 0xde, 0xb9, 0x12, + 0x8c, 0x19, 0xf6, 0xf4, 0xbb, 0xb0, 0x41, 0xce, 0x45, 0x3b, 0xf0, 0x0c, 0xad, 0xaa, 0xd5, 0xca, + 0xee, 0x3a, 0x39, 0x17, 0x4d, 0x4f, 0x7f, 0x02, 0xb7, 0x10, 0xe7, 0x58, 0xb4, 0xbb, 0x21, 0xe2, + 0x3c, 0x49, 0xaf, 0xc9, 0xf4, 0x8e, 0x8c, 0x36, 0x92, 0x60, 0xd3, 0xb3, 0x3e, 0x69, 0x70, 0x47, + 0x72, 0xba, 0x34, 0xc4, 0xaf, 0x19, 0x22, 0x62, 0x45, 0x46, 0x5d, 0x87, 0x12, 0xa3, 0x21, 0x36, + 0x8a, 0x32, 0x27, 0xbf, 0xf5, 0x07, 0x50, 0x46, 0x9e, 0xc7, 0x30, 0xe7, 0x98, 0x1b, 0xa5, 0x6a, + 0xb1, 0x56, 0x76, 0xf3, 0xc0, 0xac, 0x06, 0x17, 0xc7, 0xb4, 0xf7, 0xff, 0x35, 0x9c, 0x40, 0x45, + 0x59, 0x7b, 0x4a, 0xd8, 0x0d, 0x99, 0xfb, 0x1e, 0x8c, 0xb4, 0xaf, 0xc9, 0x9f, 0xad, 0x0f, 0xc2, + 0xde, 0x69, 0xe4, 0xa1, 0x55, 0x3d, 0xb6, 0xbe, 0x68, 0x70, 0x2f, 0x73, 0xac, 0x71, 0x81, 0x88, + 0x8f, 0x5b, 0x8c, 0x46, 0x94, 0xaf, 0x6a, 0xdc, 0x7d, 0x28, 0x77, 0x25, 0x5d, 0x02, 0x48, 0xdd, + 0xdb, 0x4a, 0x03, 0x4d, 0x4f, 0x3f, 0x80, 0xad, 0x28, 0xad, 0xc2, 0x8c, 0x52, 0x9a, 0x53, 0x6b, + 0xcb, 0x5d, 0x10, 0x74, 0x1c, 0xc9, 0xb3, 0x3d, 0xc7, 0xa9, 0x2d, 0x72, 0xa2, 0x14, 0xc8, 0x26, + 0x82, 0xb2, 0xb5, 0xc5, 0x60, 0x6f, 0x91, 0x33, 0x0c, 0xfe, 0x65, 0x8f, 0xd6, 0x99, 0xfa, 0x65, + 0x59, 0xcd, 0x46, 0x32, 0x9c, 0x61, 0xf8, 0xbb, 0x46, 0x1e, 0xc1, 0x4e, 0x57, 0x21, 0xdb, 0x9d, + 0xe1, 0xa4, 0xf2, 0x76, 0x16, 0xab, 0x0f, 0xad, 0xcf, 0x1a, 0xec, 0xcf, 0x9c, 0x07, 0xa9, 0xa8, + 0xc1, 0xb0, 0x3c, 0x10, 0x4f, 0x61, 0x57, 0xdd, 0x00, 0xb9, 0xfe, 0xb4, 0xca, 0x6d, 0x36, 0xbd, + 0xe1, 0x8f, 0x1b, 0x35, 0x01, 0xfa, 0x28, 0x20, 0x02, 0x05, 0x04, 0xb3, 0x49, 0xa7, 0x53, 0x11, + 0xcb, 0x5f, 0x26, 0x47, 0x9d, 0xcf, 0xbf, 0x91, 0x33, 0x5b, 0x68, 0x6d, 0xa1, 0x50, 0x65, 0x72, + 0x6f, 0xb5, 0x10, 0x43, 0x7d, 0x55, 0xc1, 0xfa, 0x00, 0x90, 0xb8, 0x7c, 0x12, 0xf8, 0x04, 0xb3, + 0x6c, 0x64, 0xb5, 0xa9, 0x91, 0x35, 0x01, 0x10, 0xe7, 0x81, 0x4f, 0xfa, 0x98, 0x08, 0xc5, 0x9b, + 0x47, 0x66, 0x47, 0xba, 0x38, 0x3f, 0xd2, 0xdf, 0xd6, 0xa6, 0xae, 0x95, 0x9b, 0x18, 0xbb, 0xe5, + 0x9e, 0x14, 0x97, 0x7b, 0xa2, 0xfa, 0x29, 0x5d, 0x77, 0x05, 0xad, 0xcf, 0xe9, 0xd5, 0x0f, 0x41, + 0x8f, 0x18, 0x8e, 0x03, 0x3a, 0xe0, 0xed, 0x1c, 0xb6, 0x21, 0x61, 0xbb, 0x2a, 0x73, 0x9c, 0xc1, + 0xeb, 0xb0, 0xc9, 0xa5, 0x75, 0xdc, 0xd8, 0xac, 0x16, 0x6b, 0xdb, 0xcf, 0x2c, 0x7b, 0xf9, 0x63, + 0x62, 0xe7, 0x2e, 0xd7, 0x4b, 0x97, 0x3f, 0x1e, 0x16, 0x5c, 0xb5, 0xb1, 0xde, 0xbb, 0x1c, 0x99, + 0xda, 0xd5, 0xc8, 0xd4, 0x7e, 0x8e, 0x4c, 0xed, 0xeb, 0xd8, 0x2c, 0x5c, 0x8d, 0xcd, 0xc2, 0xf7, + 0xb1, 0x59, 0x80, 0xfd, 0x80, 0x5e, 0x43, 0xd7, 0xd2, 0xce, 0x5e, 0xf8, 0x81, 0xb8, 0x18, 0x74, + 0xec, 0x2e, 0xed, 0x3b, 0x39, 0xe8, 0x30, 0xa0, 0x53, 0x2b, 0xe7, 0x63, 0xfe, 0xea, 0x89, 0x61, + 0x84, 0x79, 0x67, 0x43, 0x3e, 0x62, 0xcf, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x71, 0x63, 0xc5, + 0xb1, 0x19, 0x07, 0x00, 0x00, +} + +func (m *EventNFTRegistered) 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 *EventNFTRegistered) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventNFTRegistered) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.NftId) > 0 { + i -= len(m.NftId) + copy(dAtA[i:], m.NftId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRoleGranted) 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 *EventRoleGranted) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRoleGranted) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Addresses) > 0 { + for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Addresses[iNdEx]) + copy(dAtA[i:], m.Addresses[iNdEx]) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Addresses[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Role) > 0 { + i -= len(m.Role) + copy(dAtA[i:], m.Role) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Role))) + i-- + dAtA[i] = 0x1a + } + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.NftId) > 0 { + i -= len(m.NftId) + copy(dAtA[i:], m.NftId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRoleRevoked) 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 *EventRoleRevoked) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRoleRevoked) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Addresses) > 0 { + for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Addresses[iNdEx]) + copy(dAtA[i:], m.Addresses[iNdEx]) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Addresses[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Role) > 0 { + i -= len(m.Role) + copy(dAtA[i:], m.Role) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Role))) + i-- + dAtA[i] = 0x1a + } + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.NftId) > 0 { + i -= len(m.NftId) + copy(dAtA[i:], m.NftId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventNFTUnregistered) 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 *EventNFTUnregistered) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventNFTUnregistered) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.NftId) > 0 { + i -= len(m.NftId) + copy(dAtA[i:], m.NftId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRegistryBulkUpdated) 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 *EventRegistryBulkUpdated) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRegistryBulkUpdated) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.NftId) > 0 { + i -= len(m.NftId) + copy(dAtA[i:], m.NftId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRoleChangeProposed) 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 *EventRoleChangeProposed) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRoleChangeProposed) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Proposer) > 0 { + i -= len(m.Proposer) + copy(dAtA[i:], m.Proposer) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Proposer))) + i-- + dAtA[i] = 0x22 + } + if len(m.ChangeId) > 0 { + i -= len(m.ChangeId) + copy(dAtA[i:], m.ChangeId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.ChangeId))) + i-- + dAtA[i] = 0x1a + } + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.NftId) > 0 { + i -= len(m.NftId) + copy(dAtA[i:], m.NftId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRoleChangeApproved) 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 *EventRoleChangeApproved) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRoleChangeApproved) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Approver) > 0 { + i -= len(m.Approver) + copy(dAtA[i:], m.Approver) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Approver))) + i-- + dAtA[i] = 0x12 + } + if len(m.ChangeId) > 0 { + i -= len(m.ChangeId) + copy(dAtA[i:], m.ChangeId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.ChangeId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRoleChangeApplied) 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 *EventRoleChangeApplied) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRoleChangeApplied) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChangeId) > 0 { + i -= len(m.ChangeId) + copy(dAtA[i:], m.ChangeId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.ChangeId))) + i-- + dAtA[i] = 0x1a + } + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.NftId) > 0 { + i -= len(m.NftId) + copy(dAtA[i:], m.NftId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRoleChangeCancelled) 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 *EventRoleChangeCancelled) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRoleChangeCancelled) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.CancelledBy) > 0 { + i -= len(m.CancelledBy) + copy(dAtA[i:], m.CancelledBy) + i = encodeVarintEvents(dAtA, i, uint64(len(m.CancelledBy))) + i-- + dAtA[i] = 0x12 + } + if len(m.ChangeId) > 0 { + i -= len(m.ChangeId) + copy(dAtA[i:], m.ChangeId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.ChangeId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRegistryClassCreated) 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 *EventRegistryClassCreated) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRegistryClassCreated) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Maintainer) > 0 { + i -= len(m.Maintainer) + copy(dAtA[i:], m.Maintainer) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Maintainer))) + i-- + dAtA[i] = 0x1a + } + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRegistryClassUpdated) 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 *EventRegistryClassUpdated) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRegistryClassUpdated) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Maintainer) > 0 { + i -= len(m.Maintainer) + copy(dAtA[i:], m.Maintainer) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Maintainer))) + i-- + dAtA[i] = 0x12 + } + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventParamsUpdated) 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 *EventParamsUpdated) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventParamsUpdated) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *RoleSigner) 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 *RoleSigner) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoleSigner) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Addresses) > 0 { + for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Addresses[iNdEx]) + copy(dAtA[i:], m.Addresses[iNdEx]) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Addresses[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Assignment) > 0 { + i -= len(m.Assignment) + copy(dAtA[i:], m.Assignment) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Assignment))) + i-- + dAtA[i] = 0x12 + } + if len(m.Role) > 0 { + i -= len(m.Role) + copy(dAtA[i:], m.Role) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Role))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventRoleUpdated) 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 *EventRoleUpdated) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventRoleUpdated) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signers) > 0 { + for iNdEx := len(m.Signers) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Signers[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + if len(m.PreviousAddresses) > 0 { + for iNdEx := len(m.PreviousAddresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.PreviousAddresses[iNdEx]) + copy(dAtA[i:], m.PreviousAddresses[iNdEx]) + i = encodeVarintEvents(dAtA, i, uint64(len(m.PreviousAddresses[iNdEx]))) + i-- + dAtA[i] = 0x32 + } + } + if len(m.Addresses) > 0 { + for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Addresses[iNdEx]) + copy(dAtA[i:], m.Addresses[iNdEx]) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Addresses[iNdEx]))) + i-- + dAtA[i] = 0x2a + } + } + if len(m.Role) > 0 { + i -= len(m.Role) + copy(dAtA[i:], m.Role) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Role))) + i-- + dAtA[i] = 0x22 + } + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0x1a + } + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.NftId) > 0 { + i -= len(m.NftId) + copy(dAtA[i:], m.NftId) + i = encodeVarintEvents(dAtA, i, uint64(len(m.NftId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintEvents(dAtA []byte, offset int, v uint64) int { + offset -= sovEvents(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *EventNFTRegistered) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NftId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventRoleGranted) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NftId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Role) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + if len(m.Addresses) > 0 { + for _, s := range m.Addresses { + l = len(s) + n += 1 + l + sovEvents(uint64(l)) + } + } + return n +} + +func (m *EventRoleRevoked) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NftId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Role) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + if len(m.Addresses) > 0 { + for _, s := range m.Addresses { + l = len(s) + n += 1 + l + sovEvents(uint64(l)) + } + } + return n +} + +func (m *EventNFTUnregistered) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NftId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventRegistryBulkUpdated) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NftId) if l > 0 { n += 1 + l + sovEvents(uint64(l)) } - return n + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventRoleChangeProposed) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NftId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.ChangeId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Proposer) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventRoleChangeApproved) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChangeId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Approver) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventRoleChangeApplied) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NftId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.ChangeId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventRoleChangeCancelled) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChangeId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.CancelledBy) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventRegistryClassCreated) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Maintainer) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventRegistryClassUpdated) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Maintainer) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventParamsUpdated) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *RoleSigner) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Role) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Assignment) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + if len(m.Addresses) > 0 { + for _, s := range m.Addresses { + l = len(s) + n += 1 + l + sovEvents(uint64(l)) + } + } + return n +} + +func (m *EventRoleUpdated) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NftId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Role) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + if len(m.Addresses) > 0 { + for _, s := range m.Addresses { + l = len(s) + n += 1 + l + sovEvents(uint64(l)) + } + } + if len(m.PreviousAddresses) > 0 { + for _, s := range m.PreviousAddresses { + l = len(s) + n += 1 + l + sovEvents(uint64(l)) + } + } + if len(m.Signers) > 0 { + for _, e := range m.Signers { + l = e.Size() + n += 1 + l + sovEvents(uint64(l)) + } + } + return n +} + +func sovEvents(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozEvents(x uint64) (n int) { + return sovEvents(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *EventNFTRegistered) 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 ErrIntOverflowEvents + } + 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: EventNFTRegistered: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventNFTRegistered: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NftId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventRoleGranted) 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 ErrIntOverflowEvents + } + 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: EventRoleGranted: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventRoleGranted: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NftId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Role = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventRoleRevoked) 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 ErrIntOverflowEvents + } + 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: EventRoleRevoked: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventRoleRevoked: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NftId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Role = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventNFTUnregistered) 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 ErrIntOverflowEvents + } + 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: EventNFTUnregistered: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventNFTUnregistered: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NftId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventRegistryBulkUpdated) 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 ErrIntOverflowEvents + } + 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: EventRegistryBulkUpdated: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventRegistryBulkUpdated: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NftId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventRoleChangeProposed) 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 ErrIntOverflowEvents + } + 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: EventRoleChangeProposed: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventRoleChangeProposed: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NftId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChangeId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChangeId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proposer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventRoleChangeApproved) 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 ErrIntOverflowEvents + } + 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: EventRoleChangeApproved: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventRoleChangeApproved: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChangeId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChangeId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Approver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Approver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventRoleChangeApplied) 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 ErrIntOverflowEvents + } + 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: EventRoleChangeApplied: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventRoleChangeApplied: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NftId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChangeId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChangeId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventRoleChangeCancelled) 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 ErrIntOverflowEvents + } + 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: EventRoleChangeCancelled: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventRoleChangeCancelled: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChangeId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChangeId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CancelledBy", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CancelledBy = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } +func (m *EventRegistryClassCreated) 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 ErrIntOverflowEvents + } + 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: EventRegistryClassCreated: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventRegistryClassCreated: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RegistryClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Maintainer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Maintainer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } -func sovEvents(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozEvents(x uint64) (n int) { - return sovEvents(uint64((x << 1) ^ uint64((int64(x) >> 63)))) + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } -func (m *EventNFTRegistered) Unmarshal(dAtA []byte) error { +func (m *EventRegistryClassUpdated) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -716,15 +3290,15 @@ func (m *EventNFTRegistered) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: EventNFTRegistered: wiretype end group for non-group") + return fmt.Errorf("proto: EventRegistryClassUpdated: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: EventNFTRegistered: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: EventRegistryClassUpdated: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClassId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -752,11 +3326,11 @@ func (m *EventNFTRegistered) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.NftId = string(dAtA[iNdEx:postIndex]) + m.RegistryClassId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Maintainer", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -784,7 +3358,7 @@ func (m *EventNFTRegistered) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.AssetClassId = string(dAtA[iNdEx:postIndex]) + m.Maintainer = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -807,7 +3381,7 @@ func (m *EventNFTRegistered) Unmarshal(dAtA []byte) error { } return nil } -func (m *EventRoleGranted) Unmarshal(dAtA []byte) error { +func (m *EventParamsUpdated) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -830,47 +3404,65 @@ func (m *EventRoleGranted) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: EventRoleGranted: wiretype end group for non-group") + return fmt.Errorf("proto: EventParamsUpdated: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: EventRoleGranted: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: EventParamsUpdated: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowEvents - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err } - intStringLen := int(stringLen) - if intStringLen < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthEvents } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthEvents + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF } - if postIndex > l { + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RoleSigner) 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 ErrIntOverflowEvents + } + if iNdEx >= l { return io.ErrUnexpectedEOF } - m.NftId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: + 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: RoleSigner: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RoleSigner: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -898,11 +3490,11 @@ func (m *EventRoleGranted) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.AssetClassId = string(dAtA[iNdEx:postIndex]) + m.Role = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Assignment", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -930,9 +3522,9 @@ func (m *EventRoleGranted) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Role = string(dAtA[iNdEx:postIndex]) + m.Assignment = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) } @@ -985,7 +3577,7 @@ func (m *EventRoleGranted) Unmarshal(dAtA []byte) error { } return nil } -func (m *EventRoleRevoked) Unmarshal(dAtA []byte) error { +func (m *EventRoleUpdated) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1008,10 +3600,10 @@ func (m *EventRoleRevoked) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: EventRoleRevoked: wiretype end group for non-group") + return fmt.Errorf("proto: EventRoleUpdated: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: EventRoleRevoked: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: EventRoleUpdated: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1080,7 +3672,7 @@ func (m *EventRoleRevoked) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClassId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1108,11 +3700,11 @@ func (m *EventRoleRevoked) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Role = string(dAtA[iNdEx:postIndex]) + m.RegistryClassId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1140,61 +3732,11 @@ func (m *EventRoleRevoked) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) + m.Role = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipEvents(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthEvents - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *EventNFTUnregistered) 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 ErrIntOverflowEvents - } - 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: EventNFTUnregistered: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: EventNFTUnregistered: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + case 5: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1222,11 +3764,11 @@ func (m *EventNFTUnregistered) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.NftId = string(dAtA[iNdEx:postIndex]) + m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 2: + case 6: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field PreviousAddresses", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1254,63 +3796,13 @@ func (m *EventNFTUnregistered) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.AssetClassId = string(dAtA[iNdEx:postIndex]) + m.PreviousAddresses = append(m.PreviousAddresses, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipEvents(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthEvents - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *EventRegistryBulkUpdated) 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 ErrIntOverflowEvents - } - 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: EventRegistryBulkUpdated: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: EventRegistryBulkUpdated: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + case 7: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NftId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Signers", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowEvents @@ -1320,55 +3812,25 @@ func (m *EventRegistryBulkUpdated) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthEvents } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthEvents } if postIndex > l { return io.ErrUnexpectedEOF } - m.NftId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowEvents - } - 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 ErrInvalidLengthEvents - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthEvents - } - if postIndex > l { - return io.ErrUnexpectedEOF + m.Signers = append(m.Signers, RoleSigner{}) + if err := m.Signers[len(m.Signers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.AssetClassId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex diff --git a/x/registry/types/genesis.go b/x/registry/types/genesis.go index 14510947c5..abb9806b27 100644 --- a/x/registry/types/genesis.go +++ b/x/registry/types/genesis.go @@ -4,15 +4,46 @@ import "fmt" // DefaultGenesis returns the default genesis state. func DefaultGenesis() *GenesisState { - return &GenesisState{} + return &GenesisState{ + Params: DefaultParams(), + } } // Validate validates the GenesisState. func (m *GenesisState) Validate() error { + seenClasses := make(map[string]string, len(m.RegistryClasses)) + for _, class := range m.RegistryClasses { + if err := class.Validate(); err != nil { + return fmt.Errorf("registry class: %w", err) + } + if _, ok := seenClasses[class.RegistryClassId]; ok { + return fmt.Errorf("duplicate registry class id: %q", class.RegistryClassId) + } + seenClasses[class.RegistryClassId] = class.AssetClassId + } + for _, entry := range m.Entries { if err := entry.Validate(); err != nil { return fmt.Errorf("entry: %w", err) } + // An entry that references a registry class must reference one that exists in genesis; + // otherwise its authorization tier would silently fall back to params/legacy at runtime. + // The referenced class must also be for the same asset class as the entry, since a class + // only governs entries within its own asset class. + if entry.RegistryClassId != "" { + classAssetClassID, ok := seenClasses[entry.RegistryClassId] + if !ok { + return fmt.Errorf("entry %q references unknown registry class id: %q", entry.Key.String(), entry.RegistryClassId) + } + if classAssetClassID != entry.Key.AssetClassId { + return fmt.Errorf("entry %q: %w", entry.Key.String(), + NewErrCodeRegistryClassAssetMismatch(entry.RegistryClassId, classAssetClassID, entry.Key.AssetClassId)) + } + } + } + + if err := m.Params.Validate(); err != nil { + return fmt.Errorf("params: %w", err) } return nil diff --git a/x/registry/types/genesis.pb.go b/x/registry/types/genesis.pb.go index 021777c082..a551d54b6e 100644 --- a/x/registry/types/genesis.pb.go +++ b/x/registry/types/genesis.pb.go @@ -29,6 +29,13 @@ type GenesisState struct { // entries is the list of registry entries. // These entries define the initial state of the registry module. Entries []RegistryEntry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries"` + // pending_role_changes is the list of role changes awaiting approval. + // These preserve in-flight multi-party role changes across genesis export/import. + PendingRoleChanges []PendingRoleChange `protobuf:"bytes,2,rep,name=pending_role_changes,json=pendingRoleChanges,proto3" json:"pending_role_changes"` + // registry_classes is the list of registry classes defining asset class-level authorization rules. + RegistryClasses []RegistryClass `protobuf:"bytes,3,rep,name=registry_classes,json=registryClasses,proto3" json:"registry_classes"` + // params defines the registry module parameters at genesis. + Params Params `protobuf:"bytes,4,opt,name=params,proto3" json:"params"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -71,6 +78,27 @@ func (m *GenesisState) GetEntries() []RegistryEntry { return nil } +func (m *GenesisState) GetPendingRoleChanges() []PendingRoleChange { + if m != nil { + return m.PendingRoleChanges + } + return nil +} + +func (m *GenesisState) GetRegistryClasses() []RegistryClass { + if m != nil { + return m.RegistryClasses + } + return nil +} + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + func init() { proto.RegisterType((*GenesisState)(nil), "provenance.registry.v1.GenesisState") } @@ -80,21 +108,29 @@ func init() { } var fileDescriptor_1652bcf54f1aa9cb = []byte{ - // 216 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x29, 0x28, 0xca, 0x2f, - 0x4b, 0xcd, 0x4b, 0xcc, 0x4b, 0x4e, 0xd5, 0x2f, 0x4a, 0x4d, 0xcf, 0x2c, 0x2e, 0x29, 0xaa, 0xd4, - 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, - 0x17, 0x12, 0x43, 0xa8, 0xd2, 0x83, 0xa9, 0xd2, 0x2b, 0x33, 0x94, 0x12, 0x49, 0xcf, 0x4f, 0xcf, - 0x07, 0x2b, 0xd1, 0x07, 0xb1, 0x20, 0xaa, 0xa5, 0x54, 0x71, 0x98, 0x09, 0xd7, 0x09, 0x56, 0xa6, - 0x14, 0xca, 0xc5, 0xe3, 0x0e, 0xb1, 0x25, 0xb8, 0x24, 0xb1, 0x24, 0x55, 0xc8, 0x95, 0x8b, 0x3d, - 0x35, 0xaf, 0xa4, 0x28, 0x33, 0xb5, 0x58, 0x82, 0x51, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x55, 0x0f, - 0xbb, 0xb5, 0x7a, 0x41, 0x50, 0xb6, 0x6b, 0x5e, 0x49, 0x51, 0xa5, 0x13, 0xcb, 0x89, 0x7b, 0xf2, - 0x0c, 0x41, 0x30, 0xbd, 0x4e, 0xd9, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, - 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0xc0, - 0x25, 0x99, 0x99, 0x8f, 0xc3, 0xc4, 0x00, 0xc6, 0x28, 0x93, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, - 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x84, 0x22, 0xdd, 0xcc, 0x7c, 0x24, 0x9e, 0x7e, 0x05, 0xc2, 0x3f, - 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0x60, 0xaf, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, - 0xd9, 0xca, 0x68, 0xcf, 0x47, 0x01, 0x00, 0x00, + // 337 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x41, 0x4b, 0x02, 0x41, + 0x14, 0xc7, 0x77, 0x55, 0x0c, 0xc6, 0xa0, 0x58, 0x24, 0x36, 0x0f, 0x93, 0x54, 0x82, 0x05, 0xed, + 0xa2, 0x75, 0xec, 0xa4, 0x48, 0x57, 0x31, 0xe8, 0xd0, 0x45, 0xc6, 0xed, 0x31, 0x0e, 0xe9, 0xbc, + 0x65, 0x66, 0x94, 0xec, 0x53, 0xf4, 0xb1, 0x3c, 0x85, 0xc7, 0x4e, 0x11, 0xfa, 0x45, 0xc2, 0xdd, + 0x31, 0x25, 0x5a, 0xe8, 0xf6, 0x76, 0xe7, 0xf7, 0xff, 0xf1, 0x9f, 0x79, 0xe4, 0x3c, 0x56, 0x38, + 0x05, 0xc9, 0x64, 0x04, 0xa1, 0x02, 0x2e, 0xb4, 0x51, 0xb3, 0x70, 0xda, 0x08, 0x39, 0x48, 0xd0, + 0x42, 0x07, 0xb1, 0x42, 0x83, 0xde, 0xd1, 0x96, 0x0a, 0x36, 0x54, 0x30, 0x6d, 0x54, 0xca, 0x1c, + 0x39, 0x26, 0x48, 0xb8, 0x9e, 0x52, 0xba, 0x52, 0xcb, 0x70, 0xfe, 0x24, 0x53, 0xec, 0x32, 0x03, + 0x63, 0x13, 0x33, 0x44, 0x25, 0x5e, 0x99, 0x11, 0x28, 0x2d, 0x7b, 0x96, 0xc1, 0xc6, 0x4c, 0xb1, + 0xb1, 0x6d, 0x79, 0xfa, 0x9e, 0x23, 0xfb, 0x77, 0x69, 0xef, 0x7b, 0xc3, 0x0c, 0x78, 0x1d, 0xb2, + 0x07, 0xd2, 0x28, 0x01, 0xda, 0x77, 0xab, 0xf9, 0x7a, 0xa9, 0x59, 0x0b, 0xfe, 0xbe, 0x48, 0xd0, + 0xb3, 0x73, 0x47, 0x1a, 0x35, 0x6b, 0x15, 0xe6, 0x9f, 0x27, 0x4e, 0x6f, 0x93, 0xf5, 0x18, 0x29, + 0xc7, 0x20, 0x9f, 0x84, 0xe4, 0x7d, 0x85, 0x23, 0xe8, 0x47, 0x43, 0x26, 0x39, 0x68, 0x3f, 0x97, + 0x38, 0x2f, 0xb2, 0x9c, 0xdd, 0x34, 0xd3, 0xc3, 0x11, 0xb4, 0x93, 0x84, 0xf5, 0x7a, 0xf1, 0xef, + 0x03, 0xed, 0x3d, 0x90, 0xc3, 0x4d, 0xb4, 0x1f, 0x8d, 0x98, 0xd6, 0xa0, 0xfd, 0xfc, 0xff, 0x2a, + 0xb7, 0xd7, 0xb8, 0x55, 0x1f, 0xa8, 0xdd, 0x9f, 0xa0, 0xbd, 0x5b, 0x52, 0x4c, 0x9f, 0xc8, 0x2f, + 0x54, 0xdd, 0x7a, 0xa9, 0x49, 0x33, 0xcb, 0x26, 0x94, 0xd5, 0xd8, 0x4c, 0xeb, 0x79, 0xbe, 0xa4, + 0xee, 0x62, 0x49, 0xdd, 0xaf, 0x25, 0x75, 0xdf, 0x56, 0xd4, 0x59, 0xac, 0xa8, 0xf3, 0xb1, 0xa2, + 0x0e, 0x39, 0x16, 0x98, 0x61, 0xea, 0xba, 0x8f, 0x37, 0x5c, 0x98, 0xe1, 0x64, 0x10, 0x44, 0x38, + 0x0e, 0xb7, 0xd0, 0x95, 0xc0, 0x9d, 0xaf, 0xf0, 0x65, 0xbb, 0x47, 0x33, 0x8b, 0x41, 0x0f, 0x8a, + 0xc9, 0x12, 0xaf, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x9c, 0xbe, 0x51, 0x50, 0x92, 0x02, 0x00, + 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -117,6 +153,44 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.RegistryClasses) > 0 { + for iNdEx := len(m.RegistryClasses) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RegistryClasses[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.PendingRoleChanges) > 0 { + for iNdEx := len(m.PendingRoleChanges) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PendingRoleChanges[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } if len(m.Entries) > 0 { for iNdEx := len(m.Entries) - 1; iNdEx >= 0; iNdEx-- { { @@ -157,6 +231,20 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } + if len(m.PendingRoleChanges) > 0 { + for _, e := range m.PendingRoleChanges { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.RegistryClasses) > 0 { + for _, e := range m.RegistryClasses { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) return n } @@ -229,6 +317,107 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PendingRoleChanges", 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.PendingRoleChanges = append(m.PendingRoleChanges, PendingRoleChange{}) + if err := m.PendingRoleChanges[len(m.PendingRoleChanges)-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 RegistryClasses", 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.RegistryClasses = append(m.RegistryClasses, RegistryClass{}) + if err := m.RegistryClasses[len(m.RegistryClasses)-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 Params", 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.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/registry/types/genesis_test.go b/x/registry/types/genesis_test.go index 095d9feb62..d223f3b8fc 100644 --- a/x/registry/types/genesis_test.go +++ b/x/registry/types/genesis_test.go @@ -321,18 +321,26 @@ func TestGenesisState_Validate(t *testing.T) { expErr: "", }, { - name: "valid entry - multiple addresses", + name: "valid entry - references existing registry class", genesis: &types.GenesisState{ + RegistryClasses: []types.RegistryClass{ + { + RegistryClassId: "class-a", + AssetClassId: "class1", + Maintainer: validAddr, + }, + }, Entries: []types.RegistryEntry{ { Key: &types.RegistryKey{ AssetClassId: "class1", NftId: "nft1", }, + RegistryClassId: "class-a", Roles: []types.RolesEntry{ { Role: types.RegistryRole_REGISTRY_ROLE_ORIGINATOR, - Addresses: []string{validAddr, "cosmos1w6t0l7z0yerj49ehnqwqaayxqpe3u7e23edgma"}, + Addresses: []string{validAddr}, }, }, }, @@ -340,6 +348,62 @@ func TestGenesisState_Validate(t *testing.T) { }, expErr: "", }, + { + name: "invalid entry - references unknown registry class", + genesis: &types.GenesisState{ + RegistryClasses: []types.RegistryClass{ + { + RegistryClassId: "class-a", + AssetClassId: "class1", + Maintainer: validAddr, + }, + }, + Entries: []types.RegistryEntry{ + { + Key: &types.RegistryKey{ + AssetClassId: "class1", + NftId: "nft1", + }, + RegistryClassId: "class-missing", + Roles: []types.RolesEntry{ + { + Role: types.RegistryRole_REGISTRY_ROLE_ORIGINATOR, + Addresses: []string{validAddr}, + }, + }, + }, + }, + }, + expErr: "references unknown registry class id", + }, + { + name: "invalid entry - references class for different asset class", + genesis: &types.GenesisState{ + RegistryClasses: []types.RegistryClass{ + { + RegistryClassId: "class-a", + AssetClassId: "class1", + Maintainer: validAddr, + }, + }, + Entries: []types.RegistryEntry{ + { + Key: &types.RegistryKey{ + AssetClassId: "class2", + NftId: "nft1", + }, + RegistryClassId: "class-a", + Roles: []types.RolesEntry{ + { + Role: types.RegistryRole_REGISTRY_ROLE_ORIGINATOR, + Addresses: []string{validAddr}, + }, + }, + }, + }, + }, + expErr: "registry class \"class-a\" is for asset class \"class1\", not \"class2\"", + }, } for _, tc := range tests { diff --git a/x/registry/types/msgs.go b/x/registry/types/msgs.go index fb07d4b58c..62feb80b2f 100644 --- a/x/registry/types/msgs.go +++ b/x/registry/types/msgs.go @@ -14,6 +14,12 @@ var AllRequestMsgs = []sdk.Msg{ (*MsgRevokeRole)(nil), (*MsgUnregisterNFT)(nil), (*MsgRegistryBulkUpdate)(nil), + (*MsgSetRoles)(nil), + (*MsgProposeRoleChange)(nil), + (*MsgApproveRoleChange)(nil), + (*MsgCreateRegistryClass)(nil), + (*MsgUpdateRegistryClassRoleAuthorization)(nil), + (*MsgUpdateParams)(nil), } // ValidateBasic validates the MsgRegisterNFT message @@ -35,6 +41,13 @@ func (m MsgRegisterNFT) ValidateBasic() error { } } + // registry_class_id is optional; validate format only when set. + if m.RegistryClassId != "" { + if err := ValidateRegistryClassID(m.RegistryClassId); err != nil { + errs = append(errs, NewErrCodeInvalidField("registry_class_id", "%s", err)) + } + } + return errors.Join(errs...) } @@ -82,6 +95,179 @@ func (m MsgRevokeRole) ValidateBasic() error { return errors.Join(errs...) } +// ValidateBasic validates the MsgSetRoles message +func (m MsgSetRoles) ValidateBasic() error { + var errs []error + if _, err := sdk.AccAddressFromBech32(m.Signer); err != nil { + errs = append(errs, NewErrCodeInvalidField("signer", "%s", err)) + } + + if err := m.Key.Validate(); err != nil { + errs = append(errs, NewErrCodeInvalidField("key", "%s", err)) + } + + errs = append(errs, validateRoleUpdates(m.RoleUpdates)...) + + return errors.Join(errs...) +} + +// ValidateBasic validates the MsgProposeRoleChange message +func (m MsgProposeRoleChange) ValidateBasic() error { + var errs []error + if _, err := sdk.AccAddressFromBech32(m.Signer); err != nil { + errs = append(errs, NewErrCodeInvalidField("signer", "%s", err)) + } + + if err := m.Key.Validate(); err != nil { + errs = append(errs, NewErrCodeInvalidField("key", "%s", err)) + } + + errs = append(errs, validateRoleUpdates(m.RoleUpdates)...) + + return errors.Join(errs...) +} + +// validateRoleUpdates validates a batch of desired-state role updates. Each role must be a known, +// specified enum value and may appear at most once across the batch (the batch is a desired-state +// map, so a repeated role is ambiguous). Addresses within an update must be valid and free of +// duplicates, matching the invariants enforced by RolesEntry.Validate once the batch is applied. +func validateRoleUpdates(updates []RoleUpdate) []error { + if len(updates) == 0 { + return []error{NewErrCodeInvalidField("role_updates", "at least one role update is required")} + } + + var errs []error + seenRoles := make(map[RegistryRole]bool, len(updates)) + for i, update := range updates { + if err := update.Role.Validate(); err != nil { + errs = append(errs, NewErrCodeInvalidField("role_updates", "%d: role %s", i, err)) + } else if seenRoles[update.Role] { + errs = append(errs, NewErrCodeInvalidField("role_updates", "%d: duplicate role %s", i, update.Role.ShortString())) + } else { + seenRoles[update.Role] = true + } + + seenAddrs := make(map[string]bool, len(update.Addresses)) + for _, addr := range update.Addresses { + if _, err := sdk.AccAddressFromBech32(addr); err != nil { + errs = append(errs, NewErrCodeInvalidField("role_updates", "%d: invalid address: %s", i, err)) + continue + } + if seenAddrs[addr] { + errs = append(errs, NewErrCodeInvalidField("role_updates", "%d: duplicate address: %s", i, addr)) + continue + } + seenAddrs[addr] = true + } + } + return errs +} + +// ValidateBasic validates the MsgApproveRoleChange message +func (m MsgApproveRoleChange) ValidateBasic() error { + var errs []error + if _, err := sdk.AccAddressFromBech32(m.Signer); err != nil { + errs = append(errs, NewErrCodeInvalidField("signer", "%s", err)) + } + + if len(m.ChangeId) == 0 { + errs = append(errs, NewErrCodeInvalidField("change_id", "change_id is required")) + } + + return errors.Join(errs...) +} + +// ValidateBasic validates the MsgCancelRoleChange message +func (m MsgCancelRoleChange) ValidateBasic() error { + var errs []error + if _, err := sdk.AccAddressFromBech32(m.Signer); err != nil { + errs = append(errs, NewErrCodeInvalidField("signer", "%s", err)) + } + + if len(m.ChangeId) == 0 { + errs = append(errs, NewErrCodeInvalidField("change_id", "change_id is required")) + } + + return errors.Join(errs...) +} + +// ValidateBasic validates the MsgAssociateRegistryClass message. +func (m MsgAssociateRegistryClass) ValidateBasic() error { + var errs []error + if _, err := sdk.AccAddressFromBech32(m.Signer); err != nil { + errs = append(errs, NewErrCodeInvalidField("signer", "%s", err)) + } + + if m.Key == nil { + errs = append(errs, NewErrCodeInvalidField("key", "key is required")) + } + + if len(m.RegistryClassId) == 0 { + errs = append(errs, NewErrCodeInvalidField("registry_class_id", "registry_class_id is required")) + } + + return errors.Join(errs...) +} + +// ValidateBasic validates the MsgCreateRegistryClass message +func (m MsgCreateRegistryClass) ValidateBasic() error { + var errs []error + if _, err := sdk.AccAddressFromBech32(m.Signer); err != nil { + errs = append(errs, NewErrCodeInvalidField("signer", "%s", err)) + } + + if _, err := sdk.AccAddressFromBech32(m.Maintainer); err != nil { + errs = append(errs, NewErrCodeInvalidField("maintainer", "%s", err)) + } + + // The signer must be the maintainer being set. + if m.Signer != m.Maintainer { + errs = append(errs, NewErrCodeInvalidField("signer", "signer %q must match maintainer %q", m.Signer, m.Maintainer)) + } + + if err := ValidateRegistryClassID(m.RegistryClassId); err != nil { + errs = append(errs, NewErrCodeInvalidField("registry_class_id", "%s", err)) + } + + if err := ValidateClassID(m.AssetClassId); err != nil { + errs = append(errs, NewErrCodeInvalidField("asset_class_id", "%s", err)) + } + + errs = append(errs, validateRoleAuthorizations(m.RoleAuthorizations)...) + + return errors.Join(errs...) +} + +// ValidateBasic validates the MsgUpdateRegistryClassRoleAuthorization message +func (m MsgUpdateRegistryClassRoleAuthorization) ValidateBasic() error { + var errs []error + if _, err := sdk.AccAddressFromBech32(m.Signer); err != nil { + errs = append(errs, NewErrCodeInvalidField("signer", "%s", err)) + } + + if err := ValidateRegistryClassID(m.RegistryClassId); err != nil { + errs = append(errs, NewErrCodeInvalidField("registry_class_id", "%s", err)) + } + + errs = append(errs, validateRoleAuthorizations(m.RoleAuthorizations)...) + + return errors.Join(errs...) +} + +// ValidateBasic validates the MsgUpdateParams message +func (m MsgUpdateParams) ValidateBasic() error { + var errs []error + if _, err := sdk.AccAddressFromBech32(m.Authority); err != nil { + errs = append(errs, NewErrCodeInvalidField("authority", "%s", err)) + } + + if err := m.Params.Validate(); err != nil { + errs = append(errs, NewErrCodeInvalidField("params", "%s", err)) + } + + return errors.Join(errs...) +} + // ValidateBasic validates the MsgUnregisterNFT message func (m MsgUnregisterNFT) ValidateBasic() error { var errs []error @@ -166,6 +352,71 @@ func (m QueryHasRoleRequest) Validate() error { return errors.Join(errs...) } +// Validate validates the QueryPendingRoleChangeRequest +func (m QueryPendingRoleChangeRequest) Validate() error { + if len(m.Id) == 0 { + return NewErrCodeInvalidField("id", "id cannot be empty") + } + return nil +} + +// Validate validates the QueryPendingRoleChangesRequest +func (m QueryPendingRoleChangesRequest) Validate() error { + // The key is optional; validate it only when provided. + if m.Key != nil { + return m.Key.Validate() + } + return nil +} + +// Validate validates the QueryRegistryClassRequest +func (m QueryRegistryClassRequest) Validate() error { + if len(m.RegistryClassId) == 0 { + return NewErrCodeInvalidField("registry_class_id", "registry_class_id cannot be empty") + } + if err := ValidateRegistryClassID(m.RegistryClassId); err != nil { + return NewErrCodeInvalidField("registry_class_id", "%v", err) + } + return nil +} + +// Validate validates the QueryRegistryClassesRequest +func (m QueryRegistryClassesRequest) Validate() error { + // There's nothing to validate; pagination is optional. + return nil +} + +// Validate validates the QueryValidateRoleChangeRequest. Beyond requiring a key and at least one +// role update, it applies the same role-update invariants as MsgSetRoles/MsgProposeRoleChange +// (known/specified roles, no duplicate roles, valid and non-duplicate addresses) and verifies that +// each approver is a valid bech32 address, so malformed requests fail fast with a precise error +// rather than surfacing as a confusing authorization or policy-evaluation failure later. +func (m QueryValidateRoleChangeRequest) Validate() error { + var errs []error + if m.Key == nil { + errs = append(errs, NewErrCodeInvalidField("key", "key is required")) + } else if err := m.Key.Validate(); err != nil { + errs = append(errs, NewErrCodeInvalidField("key", "%s", err)) + } + + errs = append(errs, validateRoleUpdates(m.RoleUpdates)...) + + seenApprovers := make(map[string]bool, len(m.Approvers)) + for _, approver := range m.Approvers { + if _, err := sdk.AccAddressFromBech32(approver); err != nil { + errs = append(errs, NewErrCodeInvalidField("approvers", "invalid address: %s", err)) + continue + } + if seenApprovers[approver] { + errs = append(errs, NewErrCodeInvalidField("approvers", "duplicate address: %s", approver)) + continue + } + seenApprovers[approver] = true + } + + return errors.Join(errs...) +} + // ValidateStringLength checks several conditions in order: // 1. length is not between the minimum and maximum length returns an ErrCodeInvalidField error. // 2. contains whitespace returns an ErrCodeInvalidField error. diff --git a/x/registry/types/msgs_test.go b/x/registry/types/msgs_test.go index 91b9657671..dd241eccbf 100644 --- a/x/registry/types/msgs_test.go +++ b/x/registry/types/msgs_test.go @@ -13,13 +13,20 @@ import ( func TestAllMsgsGetSigners(t *testing.T) { msgMakers := []testutil.MsgMaker{ func(signer string) sdk.Msg { return &MsgRegisterNFT{Signer: signer} }, - func(signer string) sdk.Msg { return &MsgGrantRole{Signer: signer} }, - func(signer string) sdk.Msg { return &MsgRevokeRole{Signer: signer} }, func(signer string) sdk.Msg { return &MsgUnregisterNFT{Signer: signer} }, func(signer string) sdk.Msg { return &MsgRegistryBulkUpdate{Signer: signer} }, + func(signer string) sdk.Msg { return &MsgProposeRoleChange{Signer: signer} }, + func(signer string) sdk.Msg { return &MsgApproveRoleChange{Signer: signer} }, + func(signer string) sdk.Msg { return &MsgGrantRole{Signer: signer} }, + func(signer string) sdk.Msg { return &MsgRevokeRole{Signer: signer} }, + func(signer string) sdk.Msg { return &MsgSetRoles{Signer: signer} }, + func(signer string) sdk.Msg { return &MsgCreateRegistryClass{Signer: signer} }, + func(signer string) sdk.Msg { return &MsgUpdateRegistryClassRoleAuthorization{Signer: signer} }, + func(signer string) sdk.Msg { return &MsgUpdateParams{Authority: signer} }, } + msgMakersMulti := []testutil.MsgMakerMulti{} - testutil.RunGetSignersTests(t, AllRequestMsgs, msgMakers, nil) + testutil.RunGetSignersTests(t, AllRequestMsgs, msgMakers, msgMakersMulti) } func TestMsgRegisterNFT_ValidateBasic(t *testing.T) { @@ -116,6 +123,104 @@ func TestMsgRevokeRole_ValidateBasic(t *testing.T) { } } +func TestMsgSetRoles_ValidateBasic(t *testing.T) { + validAddr := sdk.AccAddress("setroles_signer________").String() + otherAddr := sdk.AccAddress("other_addr3___________").String() + validKey := &RegistryKey{AssetClassId: "aclass", NftId: "nft1"} + validUpdate := RoleUpdate{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{otherAddr}} + + tests := []struct { + name string + msg MsgSetRoles + exp string + }{ + {name: "valid", msg: MsgSetRoles{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}}}, + {name: "valid clear role", msg: MsgSetRoles{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER}}}}, + {name: "empty signer", msg: MsgSetRoles{Signer: "", Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}}, exp: "invalid signer: empty address"}, + {name: "bad signer", msg: MsgSetRoles{Signer: "bad", Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}}, exp: "invalid signer: decoding bech32"}, + {name: "nil key", msg: MsgSetRoles{Signer: validAddr, Key: nil, RoleUpdates: []RoleUpdate{validUpdate}}, exp: "invalid key: registry key cannot be nil"}, + {name: "no role_updates", msg: MsgSetRoles{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{}}, exp: "invalid role_updates: at least one role update is required"}, + {name: "unspecified role", msg: MsgSetRoles{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_UNSPECIFIED}}}, exp: "invalid role_updates: 0: role cannot be unspecified"}, + {name: "unknown role enum", msg: MsgSetRoles{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole(999), Addresses: []string{otherAddr}}}}, exp: "invalid role_updates: 0: role unknown registry_role enum value: 999"}, + {name: "duplicate role", msg: MsgSetRoles{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{otherAddr}}, {Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{validAddr}}}}, exp: "invalid role_updates: 1: duplicate role CONTROLLER"}, + {name: "duplicate address in update", msg: MsgSetRoles{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{otherAddr, otherAddr}}}}, exp: "invalid role_updates: 0: duplicate address"}, + {name: "bad address in update", msg: MsgSetRoles{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{"bad"}}}}, exp: "invalid role_updates: 0: invalid address"}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.exp == "" { + assertions.RequireErrorContents(t, err, nil) + } else { + assertions.RequireErrorContents(t, err, []string{tc.exp}) + } + }) + } +} + +func TestMsgProposeRoleChange_ValidateBasic(t *testing.T) { + validAddr := sdk.AccAddress("propose_signer_________").String() + otherAddr := sdk.AccAddress("propose_target_________").String() + validKey := &RegistryKey{AssetClassId: "aclass", NftId: "nft1"} + validUpdate := RoleUpdate{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{otherAddr}} + + tests := []struct { + name string + msg MsgProposeRoleChange + exp string + }{ + {name: "valid", msg: MsgProposeRoleChange{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}}}, + {name: "valid clear role", msg: MsgProposeRoleChange{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER}}}}, + {name: "empty signer", msg: MsgProposeRoleChange{Signer: "", Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}}, exp: "invalid signer: empty address"}, + {name: "bad signer", msg: MsgProposeRoleChange{Signer: "bad", Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}}, exp: "invalid signer: decoding bech32"}, + {name: "nil key", msg: MsgProposeRoleChange{Signer: validAddr, Key: nil, RoleUpdates: []RoleUpdate{validUpdate}}, exp: "invalid key: registry key cannot be nil"}, + {name: "no role_updates", msg: MsgProposeRoleChange{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{}}, exp: "invalid role_updates: at least one role update is required"}, + {name: "unspecified role", msg: MsgProposeRoleChange{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_UNSPECIFIED}}}, exp: "invalid role_updates: 0: role cannot be unspecified"}, + {name: "unknown role enum", msg: MsgProposeRoleChange{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole(999), Addresses: []string{otherAddr}}}}, exp: "invalid role_updates: 0: role unknown registry_role enum value: 999"}, + {name: "duplicate role", msg: MsgProposeRoleChange{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{otherAddr}}, {Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{validAddr}}}}, exp: "invalid role_updates: 1: duplicate role CONTROLLER"}, + {name: "duplicate address in update", msg: MsgProposeRoleChange{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{otherAddr, otherAddr}}}}, exp: "invalid role_updates: 0: duplicate address"}, + {name: "bad address in update", msg: MsgProposeRoleChange{Signer: validAddr, Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{"bad"}}}}, exp: "invalid role_updates: 0: invalid address"}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.exp == "" { + assertions.RequireErrorContents(t, err, nil) + } else { + assertions.RequireErrorContents(t, err, []string{tc.exp}) + } + }) + } +} + +func TestMsgApproveRoleChange_ValidateBasic(t *testing.T) { + validAddr := sdk.AccAddress("approve_signer_________").String() + + tests := []struct { + name string + msg MsgApproveRoleChange + exp string + }{ + {name: "valid", msg: MsgApproveRoleChange{Signer: validAddr, ChangeId: "abc123"}}, + {name: "empty signer", msg: MsgApproveRoleChange{Signer: "", ChangeId: "abc123"}, exp: "invalid signer: empty address"}, + {name: "bad signer", msg: MsgApproveRoleChange{Signer: "bad", ChangeId: "abc123"}, exp: "invalid signer: decoding bech32"}, + {name: "empty change_id", msg: MsgApproveRoleChange{Signer: validAddr, ChangeId: ""}, exp: "invalid change_id: change_id is required"}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.exp == "" { + assertions.RequireErrorContents(t, err, nil) + } else { + assertions.RequireErrorContents(t, err, []string{tc.exp}) + } + }) + } +} + func TestMsgUnregisterNFT_ValidateBasic(t *testing.T) { validAddr := sdk.AccAddress("unreg_signer___________").String() validKey := &RegistryKey{AssetClassId: "aclass", NftId: "nft1"} @@ -177,3 +282,37 @@ func TestMsgRegistryBulkUpdate_ValidateBasic(t *testing.T) { }) } } + +func TestQueryValidateRoleChangeRequest_Validate(t *testing.T) { + validAddr := sdk.AccAddress("vrc_approver___________").String() + otherAddr := sdk.AccAddress("vrc_other_addr_________").String() + validKey := &RegistryKey{AssetClassId: "aclass", NftId: "nft1"} + validUpdate := RoleUpdate{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{otherAddr}} + + tests := []struct { + name string + req QueryValidateRoleChangeRequest + exp string + }{ + {name: "valid", req: QueryValidateRoleChangeRequest{Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}, Approvers: []string{validAddr}}}, + {name: "valid no approvers", req: QueryValidateRoleChangeRequest{Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}}}, + {name: "nil key", req: QueryValidateRoleChangeRequest{Key: nil, RoleUpdates: []RoleUpdate{validUpdate}}, exp: "invalid key: key is required"}, + {name: "no role_updates", req: QueryValidateRoleChangeRequest{Key: validKey, RoleUpdates: []RoleUpdate{}}, exp: "invalid role_updates: at least one role update is required"}, + {name: "unspecified role", req: QueryValidateRoleChangeRequest{Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_UNSPECIFIED}}}, exp: "invalid role_updates: 0: role cannot be unspecified"}, + {name: "duplicate role", req: QueryValidateRoleChangeRequest{Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{otherAddr}}, {Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{validAddr}}}}, exp: "invalid role_updates: 1: duplicate role CONTROLLER"}, + {name: "bad address in update", req: QueryValidateRoleChangeRequest{Key: validKey, RoleUpdates: []RoleUpdate{{Role: RegistryRole_REGISTRY_ROLE_CONTROLLER, Addresses: []string{"bad"}}}}, exp: "invalid role_updates: 0: invalid address"}, + {name: "bad approver", req: QueryValidateRoleChangeRequest{Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}, Approvers: []string{"bad"}}, exp: "invalid approvers: invalid address"}, + {name: "duplicate approver", req: QueryValidateRoleChangeRequest{Key: validKey, RoleUpdates: []RoleUpdate{validUpdate}, Approvers: []string{validAddr, validAddr}}, exp: "invalid approvers: duplicate address"}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.req.Validate() + if tc.exp == "" { + assertions.RequireErrorContents(t, err, nil) + } else { + assertions.RequireErrorContents(t, err, []string{tc.exp}) + } + }) + } +} diff --git a/x/registry/types/params.go b/x/registry/types/params.go new file mode 100644 index 0000000000..94fa98adaf --- /dev/null +++ b/x/registry/types/params.go @@ -0,0 +1,29 @@ +package types + +import ( + "errors" +) + +// DefaultParams returns the default registry module parameters. By default the module defines no +// role authorization policies, which preserves the original chain behavior: every role change +// falls back to legacy NFT-owner authorization. Governance can install policies via +// MsgUpdateParams, and registry-class maintainers can define per-asset-class policies. +func DefaultParams() Params { + return Params{} +} + +// Validate validates the Params. +func (p Params) Validate() error { + var errs []error + errs = append(errs, validateRoleAuthorizations(p.RoleAuthorizations)...) + if p.PendingChangeExpiry < 0 { + errs = append(errs, NewErrCodeInvalidField("pending_change_expiry", "must be non-negative")) + } + return errors.Join(errs...) +} + +// RoleAuthorizationMap returns a map of RegistryRole -> RoleAuthorization for the params' default +// policies, for fast lookup during authorization resolution. +func (p Params) RoleAuthorizationMap() map[RegistryRole]RoleAuthorization { + return RoleAuthorizationMapFrom(p.RoleAuthorizations) +} diff --git a/x/registry/types/params.pb.go b/x/registry/types/params.pb.go new file mode 100644 index 0000000000..8546bc8153 --- /dev/null +++ b/x/registry/types/params.pb.go @@ -0,0 +1,400 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: provenance/registry/v1/params.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/protobuf/types/known/durationpb" + 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 + +// Params defines the registry module's parameters. +type Params struct { + // role_authorizations are the default authorization policies that govern role updates for + // registry entries that are not associated with a registry class. They form the middle tier of + // the two-tier resolution: a registry class policy takes precedence, then these module defaults, + // and finally roles without any policy fall back to legacy NFT-owner authorization. + RoleAuthorizations []RoleAuthorization `protobuf:"bytes,1,rep,name=role_authorizations,json=roleAuthorizations,proto3" json:"role_authorizations"` + // pending_change_expiry is how long a pending role change remains valid after it is proposed. + // Approvals received after the expiry are rejected and the change is cleaned up. + // Zero value (default) means pending changes never expire. + PendingChangeExpiry time.Duration `protobuf:"bytes,2,opt,name=pending_change_expiry,json=pendingChangeExpiry,proto3,stdduration" json:"pending_change_expiry"` +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_5e5f5edf5698b7c6, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetRoleAuthorizations() []RoleAuthorization { + if m != nil { + return m.RoleAuthorizations + } + return nil +} + +func (m *Params) GetPendingChangeExpiry() time.Duration { + if m != nil { + return m.PendingChangeExpiry + } + return 0 +} + +func init() { + proto.RegisterType((*Params)(nil), "provenance.registry.v1.Params") +} + +func init() { + proto.RegisterFile("provenance/registry/v1/params.proto", fileDescriptor_5e5f5edf5698b7c6) +} + +var fileDescriptor_5e5f5edf5698b7c6 = []byte{ + // 304 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0xc1, 0x4e, 0x2a, 0x31, + 0x14, 0x40, 0xa7, 0xef, 0x19, 0x62, 0x86, 0xdd, 0xa0, 0x06, 0x58, 0x14, 0xa2, 0x1b, 0x34, 0xb1, + 0x0d, 0xe8, 0x0f, 0x88, 0xba, 0x27, 0x6c, 0x4c, 0xdc, 0x60, 0x81, 0x5a, 0x1a, 0xa1, 0xb7, 0xe9, + 0x74, 0x08, 0xe3, 0x57, 0xb8, 0xf4, 0x7f, 0xdc, 0xb0, 0x64, 0xe9, 0x4a, 0xcd, 0xcc, 0x8f, 0x18, + 0xca, 0x90, 0x19, 0x8d, 0xec, 0x7a, 0x73, 0xcf, 0x3d, 0x39, 0xa9, 0x7f, 0xa2, 0x0d, 0xcc, 0xb9, + 0x62, 0x6a, 0xc4, 0xa9, 0xe1, 0x42, 0x86, 0xd6, 0xc4, 0x74, 0xde, 0xa6, 0x9a, 0x19, 0x36, 0x0b, + 0x89, 0x36, 0x60, 0x21, 0x38, 0xca, 0x21, 0xb2, 0x85, 0xc8, 0xbc, 0x5d, 0x3f, 0x10, 0x20, 0xc0, + 0x21, 0x74, 0xfd, 0xda, 0xd0, 0xf5, 0xb3, 0x1d, 0x4a, 0x16, 0xd9, 0x09, 0x18, 0xf9, 0xcc, 0xac, + 0x04, 0x95, 0xb1, 0x58, 0x00, 0x88, 0x29, 0xa7, 0x6e, 0x1a, 0x46, 0x8f, 0x74, 0x1c, 0x99, 0xc2, + 0xfe, 0xf8, 0x0d, 0xf9, 0xa5, 0x9e, 0x4b, 0x09, 0x1e, 0xfc, 0x8a, 0x81, 0x29, 0x1f, 0xfc, 0xd0, + 0x84, 0x55, 0xd4, 0xfc, 0xdf, 0x2a, 0x77, 0x4e, 0xc9, 0xdf, 0x89, 0xa4, 0x0f, 0x53, 0x7e, 0x55, + 0xbc, 0xe8, 0xee, 0x2d, 0x3f, 0x1a, 0x5e, 0x3f, 0x30, 0xbf, 0x17, 0x61, 0x70, 0xe7, 0x1f, 0x6a, + 0xae, 0xc6, 0x52, 0x89, 0xc1, 0x68, 0xc2, 0x94, 0xe0, 0x03, 0xbe, 0xd0, 0xd2, 0xc4, 0xd5, 0x7f, + 0x4d, 0xd4, 0x2a, 0x77, 0x6a, 0x64, 0x13, 0x4b, 0xb6, 0xb1, 0xe4, 0x26, 0x8b, 0xed, 0xee, 0xaf, + 0x9d, 0xaf, 0x9f, 0x0d, 0xd4, 0xaf, 0x64, 0x86, 0x6b, 0x27, 0xb8, 0x75, 0xf7, 0xdd, 0xa7, 0x65, + 0x82, 0xd1, 0x2a, 0xc1, 0xe8, 0x2b, 0xc1, 0xe8, 0x25, 0xc5, 0xde, 0x2a, 0xc5, 0xde, 0x7b, 0x8a, + 0x3d, 0xbf, 0x26, 0x61, 0x47, 0x79, 0x0f, 0xdd, 0x5f, 0x0a, 0x69, 0x27, 0xd1, 0x90, 0x8c, 0x60, + 0x46, 0x73, 0xe8, 0x5c, 0x42, 0x61, 0xa2, 0x8b, 0xfc, 0x8f, 0x6d, 0xac, 0x79, 0x38, 0x2c, 0xb9, + 0xbc, 0x8b, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7c, 0x36, 0xdf, 0xd4, 0xda, 0x01, 0x00, 0x00, +} + +func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.PendingChangeExpiry, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.PendingChangeExpiry):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintParams(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x12 + if len(m.RoleAuthorizations) > 0 { + for iNdEx := len(m.RoleAuthorizations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoleAuthorizations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintParams(dAtA []byte, offset int, v uint64) int { + offset -= sovParams(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.RoleAuthorizations) > 0 { + for _, e := range m.RoleAuthorizations { + l = e.Size() + n += 1 + l + sovParams(uint64(l)) + } + } + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.PendingChangeExpiry) + n += 1 + l + sovParams(uint64(l)) + return n +} + +func sovParams(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozParams(x uint64) (n int) { + return sovParams(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) 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 ErrIntOverflowParams + } + 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: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RoleAuthorizations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RoleAuthorizations = append(m.RoleAuthorizations, RoleAuthorization{}) + if err := m.RoleAuthorizations[len(m.RoleAuthorizations)-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 PendingChangeExpiry", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.PendingChangeExpiry, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipParams(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, ErrIntOverflowParams + } + 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, ErrIntOverflowParams + } + 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, ErrIntOverflowParams + } + 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, ErrInvalidLengthParams + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupParams + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthParams + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthParams = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowParams = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupParams = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/registry/types/pending.go b/x/registry/types/pending.go new file mode 100644 index 0000000000..69cd2290bc --- /dev/null +++ b/x/registry/types/pending.go @@ -0,0 +1,38 @@ +package types + +import ( + "crypto/sha256" + "encoding/hex" + "slices" + "strconv" + "strings" +) + +// NewPendingRoleChangeID computes the deterministic identifier for a pending role change. +// +// The id is a hash of the registry key and the (order-independent) set of role updates, each +// reduced to its role and the order-independent set of desired addresses. Two proposals describing +// the same batch of role updates therefore collapse onto the same pending change, so their +// approvals accumulate together. +func NewPendingRoleChangeID(key *RegistryKey, roleUpdates []RoleUpdate) string { + // Reduce each update to a canonical "role|sortedAddrs" line, then sort the lines so the id is + // independent of both address order within a role and role order across the batch. + lines := make([]string, len(roleUpdates)) + for i, update := range roleUpdates { + sorted := slices.Clone(update.Addresses) + slices.Sort(sorted) + sorted = slices.Compact(sorted) + lines[i] = strconv.Itoa(int(update.Role)) + "|" + strings.Join(sorted, ",") + } + slices.Sort(lines) + + var b strings.Builder + b.WriteString(key.AssetClassId) + b.WriteByte(0) + b.WriteString(key.NftId) + b.WriteByte(0) + b.WriteString(strings.Join(lines, "\n")) + + sum := sha256.Sum256([]byte(b.String())) + return hex.EncodeToString(sum[:]) +} diff --git a/x/registry/types/query.pb.go b/x/registry/types/query.pb.go index 54b86d6402..8846babdba 100644 --- a/x/registry/types/query.pb.go +++ b/x/registry/types/query.pb.go @@ -355,577 +355,3205 @@ func (m *QueryHasRoleResponse) GetHasRole() bool { return false } -func init() { - proto.RegisterType((*QueryGetRegistryRequest)(nil), "provenance.registry.v1.QueryGetRegistryRequest") - proto.RegisterType((*QueryGetRegistryResponse)(nil), "provenance.registry.v1.QueryGetRegistryResponse") - proto.RegisterType((*QueryGetRegistriesRequest)(nil), "provenance.registry.v1.QueryGetRegistriesRequest") - proto.RegisterType((*QueryGetRegistriesResponse)(nil), "provenance.registry.v1.QueryGetRegistriesResponse") - proto.RegisterType((*QueryHasRoleRequest)(nil), "provenance.registry.v1.QueryHasRoleRequest") - proto.RegisterType((*QueryHasRoleResponse)(nil), "provenance.registry.v1.QueryHasRoleResponse") +// QueryPendingRoleChangeRequest is the request type for the Query/PendingRoleChange RPC method. +type QueryPendingRoleChangeRequest struct { + // id is the deterministic identifier of the pending role change to retrieve. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } -func init() { - proto.RegisterFile("provenance/registry/v1/query.proto", fileDescriptor_c166c561e401a2eb) +func (m *QueryPendingRoleChangeRequest) Reset() { *m = QueryPendingRoleChangeRequest{} } +func (m *QueryPendingRoleChangeRequest) String() string { return proto.CompactTextString(m) } +func (*QueryPendingRoleChangeRequest) ProtoMessage() {} +func (*QueryPendingRoleChangeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{6} } - -var fileDescriptor_c166c561e401a2eb = []byte{ - // 605 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0x3d, 0x6f, 0xd3, 0x40, - 0x18, 0xc7, 0x73, 0x6d, 0xa1, 0xe5, 0x0a, 0x1d, 0x8e, 0x0a, 0x5c, 0x0b, 0x99, 0xc8, 0xb4, 0x50, - 0xf1, 0xe2, 0xc3, 0x01, 0x24, 0xe6, 0xf0, 0x12, 0xa0, 0x4b, 0x30, 0x62, 0x81, 0x21, 0xba, 0x38, - 0x87, 0x63, 0x25, 0xf5, 0xb9, 0xbe, 0x4b, 0x84, 0x15, 0x65, 0x61, 0x63, 0x43, 0xe2, 0x0b, 0xf4, - 0x0b, 0xb0, 0x30, 0xb3, 0xb0, 0x75, 0xac, 0xc4, 0xc2, 0x84, 0x50, 0xc2, 0x07, 0x41, 0x3e, 0x9f, - 0xf3, 0x02, 0x09, 0x4e, 0xc5, 0xe6, 0x7b, 0xee, 0xf9, 0x3f, 0xcf, 0xef, 0x79, 0x39, 0x43, 0x33, - 0x8c, 0x58, 0x97, 0x06, 0x24, 0x70, 0x29, 0x8e, 0xa8, 0xe7, 0x73, 0x11, 0xc5, 0xb8, 0x6b, 0xe3, - 0x83, 0x0e, 0x8d, 0x62, 0x2b, 0x8c, 0x98, 0x60, 0xe8, 0xc2, 0xd8, 0xc7, 0xca, 0x7c, 0xac, 0xae, - 0xad, 0x5f, 0x77, 0x19, 0xdf, 0x67, 0x1c, 0xd7, 0x09, 0xa7, 0xa9, 0x00, 0x77, 0xed, 0x3a, 0x15, - 0xc4, 0xc6, 0x21, 0xf1, 0xfc, 0x80, 0x08, 0x9f, 0x05, 0x69, 0x0c, 0x7d, 0xd3, 0x63, 0x1e, 0x93, - 0x9f, 0x38, 0xf9, 0x52, 0xd6, 0x4b, 0x1e, 0x63, 0x5e, 0x9b, 0x62, 0x12, 0xfa, 0x98, 0x04, 0x01, - 0x13, 0x52, 0xc2, 0xd5, 0xed, 0xce, 0x1c, 0xb6, 0x11, 0x83, 0x74, 0x33, 0xab, 0xf0, 0xe2, 0xf3, - 0x24, 0x79, 0x85, 0x0a, 0x47, 0xdd, 0x38, 0xf4, 0xa0, 0x43, 0xb9, 0x40, 0xf7, 0xe0, 0x72, 0x8b, - 0xc6, 0x1a, 0x28, 0x82, 0xdd, 0xf5, 0xd2, 0x15, 0x6b, 0x76, 0x1d, 0x56, 0xa6, 0xda, 0xa3, 0xb1, - 0x93, 0xf8, 0x9b, 0x2e, 0xd4, 0xfe, 0x8e, 0xc8, 0x43, 0x16, 0x70, 0x8a, 0x2a, 0x70, 0x2d, 0xd3, - 0xaa, 0xb8, 0x3b, 0x79, 0x71, 0x1f, 0x05, 0x22, 0x8a, 0xcb, 0x2b, 0x47, 0x3f, 0x2e, 0x17, 0x9c, - 0x91, 0xd8, 0x7c, 0x0f, 0xe0, 0xd6, 0x1f, 0x59, 0x7c, 0xca, 0x33, 0xf2, 0x6d, 0xb8, 0x41, 0x38, - 0xa7, 0xa2, 0xe6, 0xb6, 0x09, 0xe7, 0x35, 0xbf, 0x21, 0x93, 0x9d, 0x71, 0xce, 0x4a, 0xeb, 0x83, - 0xc4, 0xf8, 0xb4, 0x81, 0x1e, 0x43, 0x38, 0xee, 0xb4, 0xe6, 0x4a, 0x9c, 0xab, 0x56, 0x3a, 0x16, - 0x2b, 0x19, 0x8b, 0x95, 0xce, 0x51, 0x8d, 0xc5, 0xaa, 0x12, 0x8f, 0xaa, 0x0c, 0xce, 0x84, 0xd2, - 0xfc, 0x0c, 0xa0, 0x3e, 0x8b, 0x45, 0xd5, 0xbc, 0x07, 0x61, 0x34, 0xb2, 0x6a, 0xa0, 0xb8, 0x7c, - 0xd2, 0xaa, 0x27, 0xe4, 0xa8, 0x32, 0x83, 0xf9, 0x5a, 0x2e, 0x73, 0x4a, 0x32, 0x05, 0x7d, 0x08, - 0xe0, 0x79, 0x09, 0xfd, 0x84, 0x70, 0x87, 0xb5, 0xe9, 0xff, 0x0d, 0x1d, 0x69, 0x70, 0x95, 0x34, - 0x1a, 0x11, 0xe5, 0x5c, 0x5b, 0x92, 0xad, 0xce, 0x8e, 0xe8, 0x3e, 0x5c, 0x89, 0x58, 0x9b, 0x6a, - 0xcb, 0x45, 0xb0, 0xbb, 0x51, 0xda, 0xce, 0x8b, 0x28, 0x59, 0xa4, 0xc2, 0xb4, 0xe1, 0xe6, 0x34, - 0xa1, 0x6a, 0xe8, 0x16, 0x5c, 0x6b, 0x12, 0x5e, 0x93, 0x51, 0x13, 0xce, 0x35, 0x67, 0xb5, 0x99, - 0xba, 0x94, 0x3e, 0xad, 0xc0, 0x53, 0x52, 0x83, 0xbe, 0x00, 0xb8, 0x3e, 0xb1, 0x81, 0x08, 0xcf, - 0x4b, 0x3c, 0x67, 0xfb, 0xf5, 0xdb, 0x8b, 0x0b, 0x52, 0x2e, 0xf3, 0xd9, 0xbb, 0x6f, 0xbf, 0x3e, - 0x2e, 0x3d, 0x44, 0x65, 0x9c, 0xf3, 0xf4, 0x70, 0xaf, 0x45, 0x63, 0x6b, 0x7a, 0x43, 0xfb, 0xa9, - 0x31, 0x78, 0x23, 0x92, 0x03, 0x3a, 0x04, 0xf0, 0xdc, 0xd4, 0x3a, 0x21, 0x7b, 0x41, 0x9e, 0xf1, - 0x33, 0xd0, 0x4b, 0x27, 0x91, 0xa8, 0x22, 0x76, 0x65, 0x11, 0x26, 0x2a, 0xe6, 0x15, 0x81, 0xbe, - 0x02, 0xb8, 0xaa, 0x46, 0x83, 0x6e, 0xfc, 0x33, 0xd3, 0xf4, 0x8a, 0xe9, 0x37, 0x17, 0x73, 0x56, - 0x40, 0xaf, 0x25, 0xd0, 0x4b, 0xf4, 0x62, 0x1e, 0x50, 0xb6, 0x0b, 0xf9, 0x5d, 0xc5, 0x3d, 0xb5, - 0x94, 0x7d, 0xdc, 0x4b, 0x14, 0xfd, 0x72, 0xeb, 0x68, 0x60, 0x80, 0xe3, 0x81, 0x01, 0x7e, 0x0e, - 0x0c, 0xf0, 0x61, 0x68, 0x14, 0x8e, 0x87, 0x46, 0xe1, 0xfb, 0xd0, 0x28, 0xc0, 0x2d, 0x9f, 0xcd, - 0xc1, 0xac, 0x82, 0x57, 0x77, 0x3d, 0x5f, 0x34, 0x3b, 0x75, 0xcb, 0x65, 0xfb, 0x13, 0x54, 0xb7, - 0x7c, 0x36, 0xc9, 0xf8, 0x76, 0x4c, 0x29, 0xe2, 0x90, 0xf2, 0xfa, 0x69, 0xf9, 0xc7, 0xbd, 0xf3, - 0x3b, 0x00, 0x00, 0xff, 0xff, 0xb3, 0x7a, 0x07, 0x40, 0x36, 0x06, 0x00, 0x00, +func (m *QueryPendingRoleChangeRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPendingRoleChangeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPendingRoleChangeRequest.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 *QueryPendingRoleChangeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPendingRoleChangeRequest.Merge(m, src) +} +func (m *QueryPendingRoleChangeRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryPendingRoleChangeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPendingRoleChangeRequest.DiscardUnknown(m) } -// 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 +var xxx_messageInfo_QueryPendingRoleChangeRequest proto.InternalMessageInfo -// 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 { - // GetRegistry returns the registry entry for a given key. - // This method retrieves the complete registry entry including all roles and addresses. - GetRegistry(ctx context.Context, in *QueryGetRegistryRequest, opts ...grpc.CallOption) (*QueryGetRegistryResponse, error) - // GetRegistries returns all registry entries, optionally filtered by asset class ID. - // This method retrieves the complete registry entries including all roles and addresses. - GetRegistries(ctx context.Context, in *QueryGetRegistriesRequest, opts ...grpc.CallOption) (*QueryGetRegistriesResponse, error) - // HasRole returns true if the address has the specified role for the given key. - HasRole(ctx context.Context, in *QueryHasRoleRequest, opts ...grpc.CallOption) (*QueryHasRoleResponse, error) +func (m *QueryPendingRoleChangeRequest) GetId() string { + if m != nil { + return m.Id + } + return "" } -type queryClient struct { - cc grpc1.ClientConn +// QueryPendingRoleChangeResponse is the response type for the Query/PendingRoleChange RPC method. +type QueryPendingRoleChangeResponse struct { + // pending_role_change is the pending role change for the requested id. + PendingRoleChange PendingRoleChange `protobuf:"bytes,1,opt,name=pending_role_change,json=pendingRoleChange,proto3" json:"pending_role_change"` } -func NewQueryClient(cc grpc1.ClientConn) QueryClient { - return &queryClient{cc} +func (m *QueryPendingRoleChangeResponse) Reset() { *m = QueryPendingRoleChangeResponse{} } +func (m *QueryPendingRoleChangeResponse) String() string { return proto.CompactTextString(m) } +func (*QueryPendingRoleChangeResponse) ProtoMessage() {} +func (*QueryPendingRoleChangeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{7} } - -func (c *queryClient) GetRegistry(ctx context.Context, in *QueryGetRegistryRequest, opts ...grpc.CallOption) (*QueryGetRegistryResponse, error) { - out := new(QueryGetRegistryResponse) - err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/GetRegistry", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil +func (m *QueryPendingRoleChangeResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) } - -func (c *queryClient) GetRegistries(ctx context.Context, in *QueryGetRegistriesRequest, opts ...grpc.CallOption) (*QueryGetRegistriesResponse, error) { - out := new(QueryGetRegistriesResponse) - err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/GetRegistries", in, out, opts...) - if err != nil { - return nil, err +func (m *QueryPendingRoleChangeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPendingRoleChangeResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - return out, nil +} +func (m *QueryPendingRoleChangeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPendingRoleChangeResponse.Merge(m, src) +} +func (m *QueryPendingRoleChangeResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryPendingRoleChangeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPendingRoleChangeResponse.DiscardUnknown(m) } -func (c *queryClient) HasRole(ctx context.Context, in *QueryHasRoleRequest, opts ...grpc.CallOption) (*QueryHasRoleResponse, error) { - out := new(QueryHasRoleResponse) - err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/HasRole", in, out, opts...) - if err != nil { - return nil, err +var xxx_messageInfo_QueryPendingRoleChangeResponse proto.InternalMessageInfo + +func (m *QueryPendingRoleChangeResponse) GetPendingRoleChange() PendingRoleChange { + if m != nil { + return m.PendingRoleChange } - return out, nil + return PendingRoleChange{} } -// QueryServer is the server API for Query service. -type QueryServer interface { - // GetRegistry returns the registry entry for a given key. - // This method retrieves the complete registry entry including all roles and addresses. - GetRegistry(context.Context, *QueryGetRegistryRequest) (*QueryGetRegistryResponse, error) - // GetRegistries returns all registry entries, optionally filtered by asset class ID. - // This method retrieves the complete registry entries including all roles and addresses. - GetRegistries(context.Context, *QueryGetRegistriesRequest) (*QueryGetRegistriesResponse, error) - // HasRole returns true if the address has the specified role for the given key. - HasRole(context.Context, *QueryHasRoleRequest) (*QueryHasRoleResponse, error) +// QueryPendingRoleChangesRequest is the paginated request type for the Query/PendingRoleChanges +// RPC method. +type QueryPendingRoleChangesRequest struct { + // key optionally filters the results to a single registry entry. When unset, all pending role + // changes are returned. + Key *RegistryKey `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,99,opt,name=pagination,proto3" json:"pagination,omitempty"` } -// UnimplementedQueryServer can be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { +func (m *QueryPendingRoleChangesRequest) Reset() { *m = QueryPendingRoleChangesRequest{} } +func (m *QueryPendingRoleChangesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryPendingRoleChangesRequest) ProtoMessage() {} +func (*QueryPendingRoleChangesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{8} } - -func (*UnimplementedQueryServer) GetRegistry(ctx context.Context, req *QueryGetRegistryRequest) (*QueryGetRegistryResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetRegistry not implemented") +func (m *QueryPendingRoleChangesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) } -func (*UnimplementedQueryServer) GetRegistries(ctx context.Context, req *QueryGetRegistriesRequest) (*QueryGetRegistriesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetRegistries not implemented") +func (m *QueryPendingRoleChangesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPendingRoleChangesRequest.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 (*UnimplementedQueryServer) HasRole(ctx context.Context, req *QueryHasRoleRequest) (*QueryHasRoleResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method HasRole not implemented") +func (m *QueryPendingRoleChangesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPendingRoleChangesRequest.Merge(m, src) } - -func RegisterQueryServer(s grpc1.Server, srv QueryServer) { - s.RegisterService(&_Query_serviceDesc, srv) +func (m *QueryPendingRoleChangesRequest) XXX_Size() int { + return m.Size() } - -func _Query_GetRegistry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryGetRegistryRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).GetRegistry(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/provenance.registry.v1.Query/GetRegistry", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).GetRegistry(ctx, req.(*QueryGetRegistryRequest)) - } - return interceptor(ctx, in, info, handler) +func (m *QueryPendingRoleChangesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPendingRoleChangesRequest.DiscardUnknown(m) } -func _Query_GetRegistries_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryGetRegistriesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).GetRegistries(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/provenance.registry.v1.Query/GetRegistries", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).GetRegistries(ctx, req.(*QueryGetRegistriesRequest)) +var xxx_messageInfo_QueryPendingRoleChangesRequest proto.InternalMessageInfo + +func (m *QueryPendingRoleChangesRequest) GetKey() *RegistryKey { + if m != nil { + return m.Key } - return interceptor(ctx, in, info, handler) + return nil } -func _Query_HasRole_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryHasRoleRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).HasRole(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/provenance.registry.v1.Query/HasRole", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).HasRole(ctx, req.(*QueryHasRoleRequest)) +func (m *QueryPendingRoleChangesRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination } - return interceptor(ctx, in, info, handler) + return nil } -var Query_serviceDesc = _Query_serviceDesc -var _Query_serviceDesc = grpc.ServiceDesc{ - ServiceName: "provenance.registry.v1.Query", - HandlerType: (*QueryServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetRegistry", - Handler: _Query_GetRegistry_Handler, - }, - { - MethodName: "GetRegistries", - Handler: _Query_GetRegistries_Handler, - }, - { - MethodName: "HasRole", - Handler: _Query_HasRole_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "provenance/registry/v1/query.proto", +// QueryPendingRoleChangesResponse is the paginated response type for the Query/PendingRoleChanges +// RPC method. +type QueryPendingRoleChangesResponse struct { + // pending_role_changes is the collection of pending role changes. + PendingRoleChanges []PendingRoleChange `protobuf:"bytes,1,rep,name=pending_role_changes,json=pendingRoleChanges,proto3" json:"pending_role_changes"` + // pagination is the pagination details for this response. + Pagination *query.PageResponse `protobuf:"bytes,99,opt,name=pagination,proto3" json:"pagination,omitempty"` } -func (m *QueryGetRegistryRequest) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *QueryPendingRoleChangesResponse) Reset() { *m = QueryPendingRoleChangesResponse{} } +func (m *QueryPendingRoleChangesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryPendingRoleChangesResponse) ProtoMessage() {} +func (*QueryPendingRoleChangesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{9} +} +func (m *QueryPendingRoleChangesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPendingRoleChangesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPendingRoleChangesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - return dAtA[:n], nil } - -func (m *QueryGetRegistryRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +func (m *QueryPendingRoleChangesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPendingRoleChangesResponse.Merge(m, src) +} +func (m *QueryPendingRoleChangesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryPendingRoleChangesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPendingRoleChangesResponse.DiscardUnknown(m) } -func (m *QueryGetRegistryRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Key != nil { - { - size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa +var xxx_messageInfo_QueryPendingRoleChangesResponse proto.InternalMessageInfo + +func (m *QueryPendingRoleChangesResponse) GetPendingRoleChanges() []PendingRoleChange { + if m != nil { + return m.PendingRoleChanges } - return len(dAtA) - i, nil + return nil } -func (m *QueryGetRegistryResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *QueryPendingRoleChangesResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination } - return dAtA[:n], nil + return nil } -func (m *QueryGetRegistryResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// QueryRegistryClassRequest is the request type for the Query/RegistryClass RPC method. +type QueryRegistryClassRequest struct { + // registry_class_id is the unique identifier of the registry class to retrieve. + RegistryClassId string `protobuf:"bytes,1,opt,name=registry_class_id,json=registryClassId,proto3" json:"registry_class_id,omitempty"` } -func (m *QueryGetRegistryResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Registry.MarshalToSizedBuffer(dAtA[:i]) +func (m *QueryRegistryClassRequest) Reset() { *m = QueryRegistryClassRequest{} } +func (m *QueryRegistryClassRequest) String() string { return proto.CompactTextString(m) } +func (*QueryRegistryClassRequest) ProtoMessage() {} +func (*QueryRegistryClassRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{10} +} +func (m *QueryRegistryClassRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRegistryClassRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRegistryClassRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) if err != nil { - return 0, err + return nil, err } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) + return b[:n], nil } - i-- - dAtA[i] = 0xa - return len(dAtA) - i, nil +} +func (m *QueryRegistryClassRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRegistryClassRequest.Merge(m, src) +} +func (m *QueryRegistryClassRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryRegistryClassRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRegistryClassRequest.DiscardUnknown(m) } -func (m *QueryGetRegistriesRequest) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +var xxx_messageInfo_QueryRegistryClassRequest proto.InternalMessageInfo + +func (m *QueryRegistryClassRequest) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId } - return dAtA[:n], nil + return "" } -func (m *QueryGetRegistriesRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// QueryRegistryClassResponse is the response type for the Query/RegistryClass RPC method. +type QueryRegistryClassResponse struct { + // registry_class is the registry class for the requested id, including its authorization policy. + RegistryClass RegistryClass `protobuf:"bytes,1,opt,name=registry_class,json=registryClass,proto3" json:"registry_class"` } -func (m *QueryGetRegistriesRequest) 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)) +func (m *QueryRegistryClassResponse) Reset() { *m = QueryRegistryClassResponse{} } +func (m *QueryRegistryClassResponse) String() string { return proto.CompactTextString(m) } +func (*QueryRegistryClassResponse) ProtoMessage() {} +func (*QueryRegistryClassResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{11} +} +func (m *QueryRegistryClassResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRegistryClassResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRegistryClassResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } - i-- - dAtA[i] = 0x6 - i-- - dAtA[i] = 0x9a - } - if len(m.AssetClassId) > 0 { - i -= len(m.AssetClassId) - copy(dAtA[i:], m.AssetClassId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.AssetClassId))) - i-- - dAtA[i] = 0xa + return b[:n], nil } - return len(dAtA) - i, nil +} +func (m *QueryRegistryClassResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRegistryClassResponse.Merge(m, src) +} +func (m *QueryRegistryClassResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryRegistryClassResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRegistryClassResponse.DiscardUnknown(m) } -func (m *QueryGetRegistriesResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +var xxx_messageInfo_QueryRegistryClassResponse proto.InternalMessageInfo + +func (m *QueryRegistryClassResponse) GetRegistryClass() RegistryClass { + if m != nil { + return m.RegistryClass } - return dAtA[:n], nil + return RegistryClass{} } -func (m *QueryGetRegistriesResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// QueryRegistryClassesRequest is the paginated request type for the Query/RegistryClasses RPC method. +type QueryRegistryClassesRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,99,opt,name=pagination,proto3" json:"pagination,omitempty"` } -func (m *QueryGetRegistriesResponse) 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] = 0x6 - i-- - dAtA[i] = 0x9a - } - if len(m.Registries) > 0 { - for iNdEx := len(m.Registries) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Registries[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa +func (m *QueryRegistryClassesRequest) Reset() { *m = QueryRegistryClassesRequest{} } +func (m *QueryRegistryClassesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryRegistryClassesRequest) ProtoMessage() {} +func (*QueryRegistryClassesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{12} +} +func (m *QueryRegistryClassesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRegistryClassesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRegistryClassesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - return len(dAtA) - i, nil +} +func (m *QueryRegistryClassesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRegistryClassesRequest.Merge(m, src) +} +func (m *QueryRegistryClassesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryRegistryClassesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRegistryClassesRequest.DiscardUnknown(m) } -func (m *QueryHasRoleRequest) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +var xxx_messageInfo_QueryRegistryClassesRequest proto.InternalMessageInfo + +func (m *QueryRegistryClassesRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination } - return dAtA[:n], nil + return nil } -func (m *QueryHasRoleRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// QueryRegistryClassesResponse is the paginated response type for the Query/RegistryClasses RPC method. +type QueryRegistryClassesResponse struct { + // registry_classes is the collection of registry classes. + RegistryClasses []RegistryClass `protobuf:"bytes,1,rep,name=registry_classes,json=registryClasses,proto3" json:"registry_classes"` + // pagination is the pagination details for this response. + Pagination *query.PageResponse `protobuf:"bytes,99,opt,name=pagination,proto3" json:"pagination,omitempty"` } -func (m *QueryHasRoleRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Role != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.Role)) - i-- - dAtA[i] = 0x18 - } - if len(m.Address) > 0 { - i -= len(m.Address) - copy(dAtA[i:], m.Address) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) - i-- - dAtA[i] = 0x12 - } - if m.Key != nil { - { - size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) +func (m *QueryRegistryClassesResponse) Reset() { *m = QueryRegistryClassesResponse{} } +func (m *QueryRegistryClassesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryRegistryClassesResponse) ProtoMessage() {} +func (*QueryRegistryClassesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{13} +} +func (m *QueryRegistryClassesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRegistryClassesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRegistryClassesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } - i-- - dAtA[i] = 0xa + return b[:n], nil } - return len(dAtA) - i, nil +} +func (m *QueryRegistryClassesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRegistryClassesResponse.Merge(m, src) +} +func (m *QueryRegistryClassesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryRegistryClassesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRegistryClassesResponse.DiscardUnknown(m) } -func (m *QueryHasRoleResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +var xxx_messageInfo_QueryRegistryClassesResponse proto.InternalMessageInfo + +func (m *QueryRegistryClassesResponse) GetRegistryClasses() []RegistryClass { + if m != nil { + return m.RegistryClasses } - return dAtA[:n], nil + return nil } -func (m *QueryHasRoleResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +func (m *QueryRegistryClassesResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil } -func (m *QueryHasRoleResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.HasRole { - i-- - if m.HasRole { - dAtA[i] = 1 - } else { - dAtA[i] = 0 +// QueryParamsRequest is the request type for the Query/Params RPC method. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{14} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } - i-- - dAtA[i] = 0x8 + return b[:n], nil } - return len(dAtA) - i, nil +} +func (m *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) } -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 +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse is the response type for the Query/Params RPC method. +type QueryParamsResponse struct { + // params are the current registry module parameters. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` } -func (m *QueryGetRegistryRequest) Size() (n int) { - if m == nil { - return 0 + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{15} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - var l int - _ = l - if m.Key != nil { - l = m.Key.Size() - n += 1 + l + sovQuery(uint64(l)) +} +func (m *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params } - return n + return Params{} } -func (m *QueryGetRegistryResponse) Size() (n int) { - if m == nil { - return 0 +// QueryValidateRoleChangeRequest is the request type for the Query/ValidateRoleChange RPC method. +// It describes a candidate role-change batch and the set of approvers to test against each affected +// role's authorization policy. +type QueryValidateRoleChangeRequest struct { + // key identifies the registry entry the role change targets. + Key *RegistryKey `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // role_updates is the desired-state batch to evaluate (same shape as MsgSetRoles). + RoleUpdates []RoleUpdate `protobuf:"bytes,2,rep,name=role_updates,json=roleUpdates,proto3" json:"role_updates"` + // approvers is the accumulated/candidate set of approver addresses to test. + Approvers []string `protobuf:"bytes,3,rep,name=approvers,proto3" json:"approvers,omitempty"` +} + +func (m *QueryValidateRoleChangeRequest) Reset() { *m = QueryValidateRoleChangeRequest{} } +func (m *QueryValidateRoleChangeRequest) String() string { return proto.CompactTextString(m) } +func (*QueryValidateRoleChangeRequest) ProtoMessage() {} +func (*QueryValidateRoleChangeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{16} +} +func (m *QueryValidateRoleChangeRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryValidateRoleChangeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryValidateRoleChangeRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - var l int - _ = l - l = m.Registry.Size() - n += 1 + l + sovQuery(uint64(l)) - return n +} +func (m *QueryValidateRoleChangeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryValidateRoleChangeRequest.Merge(m, src) +} +func (m *QueryValidateRoleChangeRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryValidateRoleChangeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryValidateRoleChangeRequest.DiscardUnknown(m) } -func (m *QueryGetRegistriesRequest) Size() (n int) { - if m == nil { - return 0 +var xxx_messageInfo_QueryValidateRoleChangeRequest proto.InternalMessageInfo + +func (m *QueryValidateRoleChangeRequest) GetKey() *RegistryKey { + if m != nil { + return m.Key } - var l int - _ = l - l = len(m.AssetClassId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) + return nil +} + +func (m *QueryValidateRoleChangeRequest) GetRoleUpdates() []RoleUpdate { + if m != nil { + return m.RoleUpdates } - if m.Pagination != nil { - l = m.Pagination.Size() - n += 2 + l + sovQuery(uint64(l)) + return nil +} + +func (m *QueryValidateRoleChangeRequest) GetApprovers() []string { + if m != nil { + return m.Approvers } - return n + return nil } -func (m *QueryGetRegistriesResponse) Size() (n int) { - if m == nil { - return 0 +// QueryValidateRoleChangeResponse is the response type for the Query/ValidateRoleChange RPC method. +type QueryValidateRoleChangeResponse struct { + // error contains the authorization failure explanation. It is empty when the change is authorized. + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + // authorized is true if the supplied approvers satisfy every affected role's policy. + Authorized bool `protobuf:"varint,2,opt,name=authorized,proto3" json:"authorized,omitempty"` +} + +func (m *QueryValidateRoleChangeResponse) Reset() { *m = QueryValidateRoleChangeResponse{} } +func (m *QueryValidateRoleChangeResponse) String() string { return proto.CompactTextString(m) } +func (*QueryValidateRoleChangeResponse) ProtoMessage() {} +func (*QueryValidateRoleChangeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c166c561e401a2eb, []int{17} +} +func (m *QueryValidateRoleChangeResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryValidateRoleChangeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryValidateRoleChangeResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - var l int - _ = l - if len(m.Registries) > 0 { - for _, e := range m.Registries { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) +} +func (m *QueryValidateRoleChangeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryValidateRoleChangeResponse.Merge(m, src) +} +func (m *QueryValidateRoleChangeResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryValidateRoleChangeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryValidateRoleChangeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryValidateRoleChangeResponse proto.InternalMessageInfo + +func (m *QueryValidateRoleChangeResponse) GetError() string { + if m != nil { + return m.Error + } + return "" +} + +func (m *QueryValidateRoleChangeResponse) GetAuthorized() bool { + if m != nil { + return m.Authorized + } + return false +} + +func init() { + proto.RegisterType((*QueryGetRegistryRequest)(nil), "provenance.registry.v1.QueryGetRegistryRequest") + proto.RegisterType((*QueryGetRegistryResponse)(nil), "provenance.registry.v1.QueryGetRegistryResponse") + proto.RegisterType((*QueryGetRegistriesRequest)(nil), "provenance.registry.v1.QueryGetRegistriesRequest") + proto.RegisterType((*QueryGetRegistriesResponse)(nil), "provenance.registry.v1.QueryGetRegistriesResponse") + proto.RegisterType((*QueryHasRoleRequest)(nil), "provenance.registry.v1.QueryHasRoleRequest") + proto.RegisterType((*QueryHasRoleResponse)(nil), "provenance.registry.v1.QueryHasRoleResponse") + proto.RegisterType((*QueryPendingRoleChangeRequest)(nil), "provenance.registry.v1.QueryPendingRoleChangeRequest") + proto.RegisterType((*QueryPendingRoleChangeResponse)(nil), "provenance.registry.v1.QueryPendingRoleChangeResponse") + proto.RegisterType((*QueryPendingRoleChangesRequest)(nil), "provenance.registry.v1.QueryPendingRoleChangesRequest") + proto.RegisterType((*QueryPendingRoleChangesResponse)(nil), "provenance.registry.v1.QueryPendingRoleChangesResponse") + proto.RegisterType((*QueryRegistryClassRequest)(nil), "provenance.registry.v1.QueryRegistryClassRequest") + proto.RegisterType((*QueryRegistryClassResponse)(nil), "provenance.registry.v1.QueryRegistryClassResponse") + proto.RegisterType((*QueryRegistryClassesRequest)(nil), "provenance.registry.v1.QueryRegistryClassesRequest") + proto.RegisterType((*QueryRegistryClassesResponse)(nil), "provenance.registry.v1.QueryRegistryClassesResponse") + proto.RegisterType((*QueryParamsRequest)(nil), "provenance.registry.v1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "provenance.registry.v1.QueryParamsResponse") + proto.RegisterType((*QueryValidateRoleChangeRequest)(nil), "provenance.registry.v1.QueryValidateRoleChangeRequest") + proto.RegisterType((*QueryValidateRoleChangeResponse)(nil), "provenance.registry.v1.QueryValidateRoleChangeResponse") +} + +func init() { + proto.RegisterFile("provenance/registry/v1/query.proto", fileDescriptor_c166c561e401a2eb) +} + +var fileDescriptor_c166c561e401a2eb = []byte{ + // 1117 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xc4, 0x6d, 0xfe, 0xbc, 0xfc, 0x29, 0x99, 0x5a, 0xe0, 0x98, 0xb0, 0xb5, 0xa6, 0x7f, + 0x30, 0x6e, 0xd9, 0x8d, 0xdd, 0x94, 0x56, 0x55, 0x4f, 0x29, 0x10, 0x4a, 0x2e, 0x61, 0xab, 0x16, + 0x09, 0x0e, 0xd6, 0xc4, 0x1e, 0xec, 0x55, 0x9c, 0x9d, 0xed, 0xce, 0xda, 0xc2, 0x58, 0x39, 0xc0, + 0xad, 0x37, 0x24, 0x3e, 0x00, 0xfd, 0x04, 0x1c, 0x38, 0x02, 0x02, 0xc1, 0xa9, 0x17, 0xa4, 0x4a, + 0x5c, 0x38, 0x21, 0x94, 0xc0, 0xf7, 0x40, 0x3b, 0x3b, 0x6b, 0xef, 0xda, 0xde, 0xac, 0x4d, 0x73, + 0xf3, 0xce, 0xbe, 0xdf, 0x7b, 0xbf, 0xdf, 0x7b, 0x6f, 0xdf, 0x1b, 0x03, 0x71, 0x5c, 0xde, 0x61, + 0x36, 0xb5, 0x6b, 0xcc, 0x70, 0x59, 0xc3, 0x12, 0x9e, 0xdb, 0x35, 0x3a, 0x65, 0xe3, 0x49, 0x9b, + 0xb9, 0x5d, 0xdd, 0x71, 0xb9, 0xc7, 0xf1, 0xab, 0x03, 0x1b, 0x3d, 0xb4, 0xd1, 0x3b, 0xe5, 0x7c, + 0xa9, 0xc6, 0xc5, 0x21, 0x17, 0xc6, 0x3e, 0x15, 0x2c, 0x00, 0x18, 0x9d, 0xf2, 0x3e, 0xf3, 0x68, + 0xd9, 0x70, 0x68, 0xc3, 0xb2, 0xa9, 0x67, 0x71, 0x3b, 0xf0, 0x91, 0xcf, 0x36, 0x78, 0x83, 0xcb, + 0x9f, 0x86, 0xff, 0x4b, 0x9d, 0x6e, 0x34, 0x38, 0x6f, 0xb4, 0x98, 0x41, 0x1d, 0xcb, 0xa0, 0xb6, + 0xcd, 0x3d, 0x09, 0x11, 0xea, 0xed, 0xd5, 0x04, 0x6e, 0x7d, 0x0e, 0x81, 0x59, 0x29, 0xc1, 0x8c, + 0xb6, 0xbd, 0x26, 0x77, 0xad, 0x2f, 0xa2, 0x34, 0x2e, 0x27, 0xd8, 0x3a, 0xd4, 0xa5, 0x87, 0x2a, + 0x2e, 0xd9, 0x83, 0xd7, 0x3e, 0xf2, 0xd5, 0xec, 0x30, 0xcf, 0x54, 0x36, 0x26, 0x7b, 0xd2, 0x66, + 0xc2, 0xc3, 0xb7, 0x20, 0x73, 0xc0, 0xba, 0x39, 0x54, 0x40, 0xc5, 0xa5, 0xca, 0x65, 0x7d, 0x7c, + 0x62, 0xf4, 0x10, 0xb5, 0xcb, 0xba, 0xa6, 0x6f, 0x4f, 0x6a, 0x90, 0x1b, 0xf5, 0x28, 0x1c, 0x6e, + 0x0b, 0x86, 0x77, 0x60, 0x21, 0xc4, 0x2a, 0xbf, 0x57, 0xd3, 0xfc, 0xbe, 0x67, 0x7b, 0x6e, 0x77, + 0xfb, 0xdc, 0xf3, 0xbf, 0x2e, 0xcd, 0x98, 0x7d, 0x30, 0x79, 0x8a, 0x60, 0x7d, 0x28, 0x8a, 0xc5, + 0x44, 0xc8, 0xfc, 0x0a, 0xac, 0x52, 0x21, 0x98, 0x57, 0xad, 0xb5, 0xa8, 0x10, 0x55, 0xab, 0x2e, + 0x83, 0x2d, 0x9a, 0xcb, 0xf2, 0xf4, 0xbe, 0x7f, 0xf8, 0xa0, 0x8e, 0xdf, 0x07, 0x18, 0x94, 0x2e, + 0x57, 0x93, 0x74, 0xae, 0xe9, 0x41, 0x9d, 0x75, 0xbf, 0xce, 0x7a, 0xd0, 0x18, 0xaa, 0xce, 0xfa, + 0x1e, 0x6d, 0x30, 0x15, 0xc1, 0x8c, 0x20, 0xc9, 0xf7, 0x08, 0xf2, 0xe3, 0xb8, 0x28, 0xcd, 0xbb, + 0x00, 0x6e, 0xff, 0x34, 0x87, 0x0a, 0x99, 0x69, 0x55, 0x47, 0xe0, 0x78, 0x67, 0x0c, 0xe7, 0x37, + 0x53, 0x39, 0x07, 0x4c, 0x62, 0xa4, 0x9f, 0x21, 0xb8, 0x28, 0x49, 0x7f, 0x40, 0x85, 0xc9, 0x5b, + 0xec, 0xe5, 0x8a, 0x8e, 0x73, 0x30, 0x4f, 0xeb, 0x75, 0x97, 0x09, 0x91, 0x9b, 0x95, 0xa9, 0x0e, + 0x1f, 0xf1, 0x1d, 0x38, 0xe7, 0xf2, 0x16, 0xcb, 0x65, 0x0a, 0xa8, 0xb8, 0x5a, 0xb9, 0x92, 0xe6, + 0x51, 0x72, 0x91, 0x08, 0x52, 0x86, 0x6c, 0x9c, 0xa1, 0x4a, 0xe8, 0x3a, 0x2c, 0x34, 0xa9, 0xa8, + 0x4a, 0xaf, 0x3e, 0xcf, 0x05, 0x73, 0xbe, 0x19, 0x98, 0x10, 0x03, 0xde, 0x90, 0x90, 0x3d, 0x66, + 0xd7, 0x2d, 0xbb, 0xe1, 0x9f, 0xdd, 0x6f, 0x52, 0xbb, 0x5f, 0x37, 0xbc, 0x0a, 0xb3, 0xfd, 0x6e, + 0x98, 0xb5, 0xea, 0xe4, 0x4b, 0x04, 0x5a, 0x12, 0x42, 0x85, 0xab, 0xc2, 0x45, 0x27, 0x78, 0x29, + 0x43, 0x56, 0x6b, 0xf2, 0xb5, 0xca, 0xd0, 0x5b, 0x49, 0x7a, 0x46, 0xfc, 0xa9, 0x62, 0xae, 0x39, + 0xc3, 0x2f, 0xc8, 0xb7, 0x89, 0x1c, 0xc4, 0x4b, 0x56, 0xe5, 0xac, 0x3a, 0xfc, 0x77, 0x04, 0x97, + 0x12, 0x19, 0xaa, 0x34, 0x51, 0xc8, 0x8e, 0x49, 0x53, 0xd8, 0xf0, 0x53, 0xe7, 0x09, 0x8f, 0xe4, + 0xe9, 0x0c, 0x9b, 0x7f, 0x47, 0x0d, 0x8f, 0x30, 0x61, 0x72, 0x22, 0x84, 0xb9, 0x2e, 0xc1, 0x5a, + 0x48, 0x70, 0x78, 0x7e, 0x5c, 0x70, 0xa3, 0x80, 0x07, 0x75, 0xe2, 0xa8, 0x2f, 0x7f, 0xc8, 0x91, + 0x4a, 0x89, 0x09, 0xab, 0x71, 0x4f, 0x93, 0xce, 0x3c, 0xe9, 0x46, 0x25, 0x62, 0x25, 0x16, 0x93, + 0x30, 0x78, 0x7d, 0x34, 0xe2, 0xa0, 0x51, 0xce, 0xaa, 0xe2, 0xbf, 0x20, 0xd8, 0x18, 0x1f, 0x47, + 0x69, 0x7b, 0x0c, 0xaf, 0xc4, 0xb5, 0x4d, 0x3e, 0xdb, 0xa2, 0xea, 0xe2, 0x19, 0x3d, 0xcb, 0x1a, + 0x67, 0x01, 0x07, 0x2d, 0x2b, 0xb7, 0x9d, 0xd2, 0x48, 0x1e, 0xaa, 0xa9, 0x17, 0x9e, 0x2a, 0x35, + 0xf7, 0x60, 0x2e, 0xd8, 0x8a, 0xaa, 0x42, 0x5a, 0x62, 0xbb, 0x4a, 0x2b, 0x45, 0x5e, 0x61, 0xc8, + 0x6f, 0xe1, 0x07, 0xfc, 0x98, 0xb6, 0xac, 0x3a, 0xf5, 0xd8, 0xe8, 0xdc, 0xf9, 0x9f, 0x1f, 0xf0, + 0x2e, 0x2c, 0xcb, 0x8f, 0xa9, 0xed, 0xf8, 0x6e, 0xfd, 0xd9, 0xea, 0x67, 0x98, 0x24, 0xe2, 0x79, + 0x8b, 0x3d, 0x92, 0xa6, 0x8a, 0xe1, 0x92, 0xdb, 0x3f, 0x11, 0x78, 0x03, 0x16, 0xa9, 0x23, 0x91, + 0xae, 0xc8, 0x65, 0x0a, 0x99, 0xe2, 0xa2, 0x39, 0x38, 0x20, 0x1f, 0xab, 0x4f, 0x7c, 0x9c, 0x06, + 0x95, 0xa5, 0x2c, 0x9c, 0x67, 0xae, 0xcb, 0x5d, 0xf5, 0x35, 0x04, 0x0f, 0x58, 0x03, 0x08, 0x6f, + 0x1f, 0xac, 0x2e, 0xa7, 0xff, 0x82, 0x19, 0x39, 0xa9, 0xfc, 0xbb, 0x0c, 0xe7, 0xa5, 0x67, 0xfc, + 0x13, 0x82, 0xa5, 0xc8, 0xad, 0x00, 0x1b, 0x49, 0x3a, 0x12, 0x6e, 0x24, 0xf9, 0xcd, 0xc9, 0x01, + 0x01, 0x65, 0xf2, 0xe1, 0x57, 0x7f, 0xfc, 0xf3, 0xcd, 0xec, 0xbb, 0x78, 0xdb, 0x48, 0xb9, 0x5f, + 0x19, 0xbd, 0x03, 0xd6, 0xd5, 0xe3, 0xb7, 0x86, 0xa3, 0xe0, 0xd0, 0xfe, 0xcc, 0xf3, 0x1f, 0xf0, + 0x33, 0x04, 0x2b, 0xb1, 0x15, 0x8f, 0xcb, 0x13, 0xf2, 0x19, 0x5c, 0x4d, 0xf2, 0x95, 0x69, 0x20, + 0x4a, 0x44, 0x51, 0x8a, 0x20, 0xb8, 0x90, 0x26, 0x02, 0xff, 0x8a, 0x60, 0x5e, 0xad, 0x4b, 0x7c, + 0xfd, 0xd4, 0x48, 0xf1, 0xb5, 0x9f, 0xbf, 0x31, 0x99, 0xb1, 0x22, 0xf4, 0xa9, 0x24, 0xf4, 0x08, + 0x3f, 0x4c, 0x22, 0x14, 0xee, 0xe7, 0xf4, 0xac, 0x1a, 0x3d, 0x75, 0x51, 0x38, 0x32, 0x7a, 0x3e, + 0xe2, 0xc8, 0xef, 0x92, 0xb5, 0x91, 0xad, 0x80, 0x6f, 0x9d, 0x4a, 0x30, 0x69, 0xdf, 0xe7, 0xdf, + 0x99, 0x16, 0xa6, 0x14, 0xde, 0x91, 0x0a, 0x2b, 0x78, 0x33, 0x49, 0xe1, 0x98, 0x5d, 0x67, 0xf4, + 0xfc, 0x2e, 0xf9, 0x11, 0x01, 0x1e, 0x5d, 0x93, 0x78, 0x4a, 0x22, 0xfd, 0x7e, 0xb9, 0x3d, 0x35, + 0x4e, 0x29, 0xd8, 0x92, 0x0a, 0x74, 0x7c, 0x63, 0x0a, 0x05, 0x02, 0xff, 0x80, 0x60, 0x25, 0x36, + 0xa7, 0x53, 0x7a, 0x7c, 0xdc, 0x06, 0x4d, 0xe9, 0xf1, 0xb1, 0xbb, 0x92, 0x6c, 0x4b, 0xba, 0xf7, + 0xf0, 0xdd, 0xb4, 0x1e, 0x0f, 0xfa, 0xc8, 0xe8, 0x8d, 0xec, 0xe8, 0x23, 0xfc, 0x1d, 0x82, 0x0b, + 0x43, 0xfb, 0x0a, 0xdf, 0x9c, 0x9c, 0xcb, 0x20, 0xe9, 0x5b, 0xd3, 0x81, 0x94, 0x84, 0x4d, 0x29, + 0xa1, 0x84, 0x8b, 0x93, 0x49, 0x60, 0x02, 0x3f, 0x45, 0x30, 0x17, 0x6c, 0x14, 0x5c, 0x3a, 0xbd, + 0xce, 0xd1, 0x25, 0x96, 0xbf, 0x3e, 0x91, 0xad, 0x62, 0x75, 0x4d, 0xb2, 0x2a, 0x60, 0xcd, 0x38, + 0xf5, 0xef, 0x20, 0xfe, 0x19, 0x01, 0x1e, 0x9d, 0xfd, 0x29, 0x7d, 0x9b, 0xb8, 0xf0, 0x52, 0xfa, + 0x36, 0x79, 0xc9, 0x90, 0xdb, 0x92, 0x6f, 0xf9, 0x2e, 0x2a, 0x91, 0xc4, 0xd6, 0xed, 0x28, 0x78, + 0xb4, 0x77, 0xb7, 0x0f, 0x9e, 0x1f, 0x6b, 0xe8, 0xc5, 0xb1, 0x86, 0xfe, 0x3e, 0xd6, 0xd0, 0xd7, + 0x27, 0xda, 0xcc, 0x8b, 0x13, 0x6d, 0xe6, 0xcf, 0x13, 0x6d, 0x06, 0xd6, 0x2d, 0x9e, 0xc0, 0x66, + 0x0f, 0x7d, 0xb2, 0xd5, 0xb0, 0xbc, 0x66, 0x7b, 0x5f, 0xaf, 0xf1, 0xc3, 0x48, 0xb8, 0xb7, 0x2d, + 0x1e, 0x0d, 0xfe, 0xf9, 0x20, 0xbc, 0xd7, 0x75, 0x98, 0xd8, 0x9f, 0x93, 0xff, 0x9e, 0x6f, 0xfe, + 0x17, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x46, 0x55, 0xb3, 0x53, 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 + +// 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 { + // GetRegistry returns the registry entry for a given key. + // This method retrieves the complete registry entry including all roles and addresses. + GetRegistry(ctx context.Context, in *QueryGetRegistryRequest, opts ...grpc.CallOption) (*QueryGetRegistryResponse, error) + // GetRegistries returns all registry entries, optionally filtered by asset class ID. + // This method retrieves the complete registry entries including all roles and addresses. + GetRegistries(ctx context.Context, in *QueryGetRegistriesRequest, opts ...grpc.CallOption) (*QueryGetRegistriesResponse, error) + // HasRole returns true if the address has the specified role for the given key. + HasRole(ctx context.Context, in *QueryHasRoleRequest, opts ...grpc.CallOption) (*QueryHasRoleResponse, error) + // PendingRoleChange returns a single pending role change by its id. + PendingRoleChange(ctx context.Context, in *QueryPendingRoleChangeRequest, opts ...grpc.CallOption) (*QueryPendingRoleChangeResponse, error) + // PendingRoleChanges returns the pending role changes, optionally filtered by registry key. + PendingRoleChanges(ctx context.Context, in *QueryPendingRoleChangesRequest, opts ...grpc.CallOption) (*QueryPendingRoleChangesResponse, error) + // RegistryClass returns a single registry class (including its authorization policy) by id. + RegistryClass(ctx context.Context, in *QueryRegistryClassRequest, opts ...grpc.CallOption) (*QueryRegistryClassResponse, error) + // RegistryClasses returns all registry classes. + RegistryClasses(ctx context.Context, in *QueryRegistryClassesRequest, opts ...grpc.CallOption) (*QueryRegistryClassesResponse, error) + // Params returns the registry module parameters, including the default role authorization + // policies. + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) + // ValidateRoleChange performs a read-only dry-run of a role-change batch, reporting whether the + // supplied approvers would satisfy every affected role's authorization policy without writing + // any state. + ValidateRoleChange(ctx context.Context, in *QueryValidateRoleChangeRequest, opts ...grpc.CallOption) (*QueryValidateRoleChangeResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) GetRegistry(ctx context.Context, in *QueryGetRegistryRequest, opts ...grpc.CallOption) (*QueryGetRegistryResponse, error) { + out := new(QueryGetRegistryResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/GetRegistry", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) GetRegistries(ctx context.Context, in *QueryGetRegistriesRequest, opts ...grpc.CallOption) (*QueryGetRegistriesResponse, error) { + out := new(QueryGetRegistriesResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/GetRegistries", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) HasRole(ctx context.Context, in *QueryHasRoleRequest, opts ...grpc.CallOption) (*QueryHasRoleResponse, error) { + out := new(QueryHasRoleResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/HasRole", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) PendingRoleChange(ctx context.Context, in *QueryPendingRoleChangeRequest, opts ...grpc.CallOption) (*QueryPendingRoleChangeResponse, error) { + out := new(QueryPendingRoleChangeResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/PendingRoleChange", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) PendingRoleChanges(ctx context.Context, in *QueryPendingRoleChangesRequest, opts ...grpc.CallOption) (*QueryPendingRoleChangesResponse, error) { + out := new(QueryPendingRoleChangesResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/PendingRoleChanges", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) RegistryClass(ctx context.Context, in *QueryRegistryClassRequest, opts ...grpc.CallOption) (*QueryRegistryClassResponse, error) { + out := new(QueryRegistryClassResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/RegistryClass", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) RegistryClasses(ctx context.Context, in *QueryRegistryClassesRequest, opts ...grpc.CallOption) (*QueryRegistryClassesResponse, error) { + out := new(QueryRegistryClassesResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/RegistryClasses", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) ValidateRoleChange(ctx context.Context, in *QueryValidateRoleChangeRequest, opts ...grpc.CallOption) (*QueryValidateRoleChangeResponse, error) { + out := new(QueryValidateRoleChangeResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Query/ValidateRoleChange", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // GetRegistry returns the registry entry for a given key. + // This method retrieves the complete registry entry including all roles and addresses. + GetRegistry(context.Context, *QueryGetRegistryRequest) (*QueryGetRegistryResponse, error) + // GetRegistries returns all registry entries, optionally filtered by asset class ID. + // This method retrieves the complete registry entries including all roles and addresses. + GetRegistries(context.Context, *QueryGetRegistriesRequest) (*QueryGetRegistriesResponse, error) + // HasRole returns true if the address has the specified role for the given key. + HasRole(context.Context, *QueryHasRoleRequest) (*QueryHasRoleResponse, error) + // PendingRoleChange returns a single pending role change by its id. + PendingRoleChange(context.Context, *QueryPendingRoleChangeRequest) (*QueryPendingRoleChangeResponse, error) + // PendingRoleChanges returns the pending role changes, optionally filtered by registry key. + PendingRoleChanges(context.Context, *QueryPendingRoleChangesRequest) (*QueryPendingRoleChangesResponse, error) + // RegistryClass returns a single registry class (including its authorization policy) by id. + RegistryClass(context.Context, *QueryRegistryClassRequest) (*QueryRegistryClassResponse, error) + // RegistryClasses returns all registry classes. + RegistryClasses(context.Context, *QueryRegistryClassesRequest) (*QueryRegistryClassesResponse, error) + // Params returns the registry module parameters, including the default role authorization + // policies. + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) + // ValidateRoleChange performs a read-only dry-run of a role-change batch, reporting whether the + // supplied approvers would satisfy every affected role's authorization policy without writing + // any state. + ValidateRoleChange(context.Context, *QueryValidateRoleChangeRequest) (*QueryValidateRoleChangeResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) GetRegistry(ctx context.Context, req *QueryGetRegistryRequest) (*QueryGetRegistryResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetRegistry not implemented") +} +func (*UnimplementedQueryServer) GetRegistries(ctx context.Context, req *QueryGetRegistriesRequest) (*QueryGetRegistriesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetRegistries not implemented") +} +func (*UnimplementedQueryServer) HasRole(ctx context.Context, req *QueryHasRoleRequest) (*QueryHasRoleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HasRole not implemented") +} +func (*UnimplementedQueryServer) PendingRoleChange(ctx context.Context, req *QueryPendingRoleChangeRequest) (*QueryPendingRoleChangeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PendingRoleChange not implemented") +} +func (*UnimplementedQueryServer) PendingRoleChanges(ctx context.Context, req *QueryPendingRoleChangesRequest) (*QueryPendingRoleChangesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PendingRoleChanges not implemented") +} +func (*UnimplementedQueryServer) RegistryClass(ctx context.Context, req *QueryRegistryClassRequest) (*QueryRegistryClassResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegistryClass not implemented") +} +func (*UnimplementedQueryServer) RegistryClasses(ctx context.Context, req *QueryRegistryClassesRequest) (*QueryRegistryClassesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegistryClasses not implemented") +} +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} +func (*UnimplementedQueryServer) ValidateRoleChange(ctx context.Context, req *QueryValidateRoleChangeRequest) (*QueryValidateRoleChangeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ValidateRoleChange not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_GetRegistry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGetRegistryRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GetRegistry(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Query/GetRegistry", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GetRegistry(ctx, req.(*QueryGetRegistryRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_GetRegistries_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGetRegistriesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GetRegistries(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Query/GetRegistries", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GetRegistries(ctx, req.(*QueryGetRegistriesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_HasRole_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryHasRoleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).HasRole(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Query/HasRole", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).HasRole(ctx, req.(*QueryHasRoleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_PendingRoleChange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPendingRoleChangeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).PendingRoleChange(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Query/PendingRoleChange", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).PendingRoleChange(ctx, req.(*QueryPendingRoleChangeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_PendingRoleChanges_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPendingRoleChangesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).PendingRoleChanges(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Query/PendingRoleChanges", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).PendingRoleChanges(ctx, req.(*QueryPendingRoleChangesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_RegistryClass_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryRegistryClassRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).RegistryClass(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Query/RegistryClass", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).RegistryClass(ctx, req.(*QueryRegistryClassRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_RegistryClasses_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryRegistryClassesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).RegistryClasses(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Query/RegistryClasses", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).RegistryClasses(ctx, req.(*QueryRegistryClassesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_ValidateRoleChange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryValidateRoleChangeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ValidateRoleChange(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Query/ValidateRoleChange", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ValidateRoleChange(ctx, req.(*QueryValidateRoleChangeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var Query_serviceDesc = _Query_serviceDesc +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "provenance.registry.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetRegistry", + Handler: _Query_GetRegistry_Handler, + }, + { + MethodName: "GetRegistries", + Handler: _Query_GetRegistries_Handler, + }, + { + MethodName: "HasRole", + Handler: _Query_HasRole_Handler, + }, + { + MethodName: "PendingRoleChange", + Handler: _Query_PendingRoleChange_Handler, + }, + { + MethodName: "PendingRoleChanges", + Handler: _Query_PendingRoleChanges_Handler, + }, + { + MethodName: "RegistryClass", + Handler: _Query_RegistryClass_Handler, + }, + { + MethodName: "RegistryClasses", + Handler: _Query_RegistryClasses_Handler, + }, + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + { + MethodName: "ValidateRoleChange", + Handler: _Query_ValidateRoleChange_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "provenance/registry/v1/query.proto", +} + +func (m *QueryGetRegistryRequest) 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 *QueryGetRegistryRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGetRegistryRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Key != nil { + { + size, err := m.Key.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 *QueryGetRegistryResponse) 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 *QueryGetRegistryResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGetRegistryResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Registry.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 *QueryGetRegistriesRequest) 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 *QueryGetRegistriesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGetRegistriesRequest) 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] = 0x6 + i-- + dAtA[i] = 0x9a + } + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryGetRegistriesResponse) 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 *QueryGetRegistriesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGetRegistriesResponse) 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] = 0x6 + i-- + dAtA[i] = 0x9a + } + if len(m.Registries) > 0 { + for iNdEx := len(m.Registries) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Registries[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 *QueryHasRoleRequest) 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 *QueryHasRoleRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryHasRoleRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Role != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Role)) + i-- + dAtA[i] = 0x18 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + if m.Key != nil { + { + size, err := m.Key.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 *QueryHasRoleResponse) 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 *QueryHasRoleResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryHasRoleResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.HasRole { + i-- + if m.HasRole { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryPendingRoleChangeRequest) 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 *QueryPendingRoleChangeRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPendingRoleChangeRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryPendingRoleChangeResponse) 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 *QueryPendingRoleChangeResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPendingRoleChangeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.PendingRoleChange.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 *QueryPendingRoleChangesRequest) 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 *QueryPendingRoleChangesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPendingRoleChangesRequest) 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] = 0x6 + i-- + dAtA[i] = 0x9a + } + if m.Key != nil { + { + size, err := m.Key.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 *QueryPendingRoleChangesResponse) 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 *QueryPendingRoleChangesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPendingRoleChangesResponse) 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] = 0x6 + i-- + dAtA[i] = 0x9a + } + if len(m.PendingRoleChanges) > 0 { + for iNdEx := len(m.PendingRoleChanges) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PendingRoleChanges[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 *QueryRegistryClassRequest) 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 *QueryRegistryClassRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRegistryClassRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryRegistryClassResponse) 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 *QueryRegistryClassResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRegistryClassResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.RegistryClass.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 *QueryRegistryClassesRequest) 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 *QueryRegistryClassesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRegistryClassesRequest) 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] = 0x6 + i-- + dAtA[i] = 0x9a + } + return len(dAtA) - i, nil +} + +func (m *QueryRegistryClassesResponse) 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 *QueryRegistryClassesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRegistryClassesResponse) 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] = 0x6 + i-- + dAtA[i] = 0x9a + } + if len(m.RegistryClasses) > 0 { + for iNdEx := len(m.RegistryClasses) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RegistryClasses[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 *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.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 *QueryValidateRoleChangeRequest) 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 *QueryValidateRoleChangeRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryValidateRoleChangeRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Approvers) > 0 { + for iNdEx := len(m.Approvers) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Approvers[iNdEx]) + copy(dAtA[i:], m.Approvers[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Approvers[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.RoleUpdates) > 0 { + for iNdEx := len(m.RoleUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoleUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Key != nil { + { + size, err := m.Key.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 *QueryValidateRoleChangeResponse) 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 *QueryValidateRoleChangeResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryValidateRoleChangeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Authorized { + i-- + if m.Authorized { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if len(m.Error) > 0 { + i -= len(m.Error) + copy(dAtA[i:], m.Error) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Error))) + i-- + dAtA[i] = 0xa + } + 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 *QueryGetRegistryRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGetRegistryResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Registry.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryGetRegistriesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 2 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGetRegistriesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Registries) > 0 { + for _, e := range m.Registries { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 2 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryHasRoleRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Role != 0 { + n += 1 + sovQuery(uint64(m.Role)) + } + return n +} + +func (m *QueryHasRoleResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.HasRole { + n += 2 + } + return n +} + +func (m *QueryPendingRoleChangeRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryPendingRoleChangeResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.PendingRoleChange.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryPendingRoleChangesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 2 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryPendingRoleChangesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.PendingRoleChanges) > 0 { + for _, e := range m.PendingRoleChanges { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 2 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryRegistryClassRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryRegistryClassResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.RegistryClass.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryRegistryClassesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 2 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryRegistryClassesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.RegistryClasses) > 0 { + for _, e := range m.RegistryClasses { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 2 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryValidateRoleChangeRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovQuery(uint64(l)) + } + if len(m.RoleUpdates) > 0 { + for _, e := range m.RoleUpdates { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if len(m.Approvers) > 0 { + for _, s := range m.Approvers { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryValidateRoleChangeResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Error) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Authorized { + n += 2 + } + 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 *QueryGetRegistryRequest) 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: QueryGetRegistryRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGetRegistryRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", 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.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.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 *QueryGetRegistryResponse) 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: QueryGetRegistryResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGetRegistryResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Registry", 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.Registry.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 *QueryGetRegistriesRequest) 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: QueryGetRegistriesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGetRegistriesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", 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.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 99: + 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 *QueryGetRegistriesResponse) 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: QueryGetRegistriesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGetRegistriesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Registries", 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.Registries = append(m.Registries, RegistryEntry{}) + if err := m.Registries[len(m.Registries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 99: + 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 *QueryHasRoleRequest) 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: QueryHasRoleRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryHasRoleRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", 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.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", 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.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + } + m.Role = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Role |= RegistryRole(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 *QueryHasRoleResponse) 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: QueryHasRoleResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryHasRoleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HasRole", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.HasRole = bool(v != 0) + 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 *QueryPendingRoleChangeRequest) 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: QueryPendingRoleChangeRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPendingRoleChangeRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", 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.Id = 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 *QueryPendingRoleChangeResponse) 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: QueryPendingRoleChangeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPendingRoleChangeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PendingRoleChange", 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.PendingRoleChange.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 *QueryPendingRoleChangesRequest) 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: QueryPendingRoleChangesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPendingRoleChangesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", 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.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 99: + 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 *QueryPendingRoleChangesResponse) 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: QueryPendingRoleChangesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPendingRoleChangesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PendingRoleChanges", 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.PendingRoleChanges = append(m.PendingRoleChanges, PendingRoleChange{}) + if err := m.PendingRoleChanges[len(m.PendingRoleChanges)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 99: + 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 *QueryRegistryClassRequest) 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: QueryRegistryClassRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryRegistryClassRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClassId", 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.RegistryClassId = 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 m.Pagination != nil { - l = m.Pagination.Size() - n += 2 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryHasRoleRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Key != nil { - l = m.Key.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Address) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.Role != 0 { - n += 1 + sovQuery(uint64(m.Role)) - } - return n -} -func (m *QueryHasRoleResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.HasRole { - n += 2 + if iNdEx > l { + return io.ErrUnexpectedEOF } - 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)))) + return nil } -func (m *QueryGetRegistryRequest) Unmarshal(dAtA []byte) error { +func (m *QueryRegistryClassResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -948,15 +3576,15 @@ func (m *QueryGetRegistryRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryGetRegistryRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryRegistryClassResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryGetRegistryRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryRegistryClassResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClass", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -983,10 +3611,7 @@ func (m *QueryGetRegistryRequest) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Key == nil { - m.Key = &RegistryKey{} - } - if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.RegistryClass.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1011,7 +3636,7 @@ func (m *QueryGetRegistryRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryGetRegistryResponse) Unmarshal(dAtA []byte) error { +func (m *QueryRegistryClassesRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1034,15 +3659,15 @@ func (m *QueryGetRegistryResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryGetRegistryResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryRegistryClassesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryGetRegistryResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryRegistryClassesRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: + case 99: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Registry", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1069,7 +3694,10 @@ func (m *QueryGetRegistryResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Registry.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1094,7 +3722,7 @@ func (m *QueryGetRegistryResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryGetRegistriesRequest) Unmarshal(dAtA []byte) error { +func (m *QueryRegistryClassesResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1117,17 +3745,17 @@ func (m *QueryGetRegistriesRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryGetRegistriesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryRegistryClassesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryGetRegistriesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryRegistryClassesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClasses", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1137,23 +3765,25 @@ func (m *QueryGetRegistriesRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthQuery } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthQuery } if postIndex > l { return io.ErrUnexpectedEOF } - m.AssetClassId = string(dAtA[iNdEx:postIndex]) + m.RegistryClasses = append(m.RegistryClasses, RegistryClass{}) + if err := m.RegistryClasses[len(m.RegistryClasses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex case 99: if wireType != 2 { @@ -1185,7 +3815,7 @@ func (m *QueryGetRegistriesRequest) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Pagination == nil { - m.Pagination = &query.PageRequest{} + m.Pagination = &query.PageResponse{} } if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -1212,7 +3842,7 @@ func (m *QueryGetRegistriesRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryGetRegistriesResponse) Unmarshal(dAtA []byte) error { +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1235,49 +3865,65 @@ func (m *QueryGetRegistriesResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryGetRegistriesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryGetRegistriesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Registries", 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 - } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err } - if msglen < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF } - if postIndex > l { + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsResponse) 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 } - m.Registries = append(m.Registries, RegistryEntry{}) - if err := m.Registries[len(m.Registries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break } - iNdEx = postIndex - case 99: + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: 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) + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1304,10 +3950,7 @@ func (m *QueryGetRegistriesResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Pagination == nil { - m.Pagination = &query.PageResponse{} - } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1332,7 +3975,7 @@ func (m *QueryGetRegistriesResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryHasRoleRequest) Unmarshal(dAtA []byte) error { +func (m *QueryValidateRoleChangeRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1355,10 +3998,10 @@ func (m *QueryHasRoleRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryHasRoleRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryValidateRoleChangeRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryHasRoleRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryValidateRoleChangeRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1399,9 +4042,9 @@ func (m *QueryHasRoleRequest) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RoleUpdates", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1411,29 +4054,31 @@ func (m *QueryHasRoleRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthQuery } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthQuery } if postIndex > l { return io.ErrUnexpectedEOF } - m.Address = string(dAtA[iNdEx:postIndex]) + m.RoleUpdates = append(m.RoleUpdates, RoleUpdate{}) + if err := m.RoleUpdates[len(m.RoleUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Approvers", wireType) } - m.Role = 0 + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1443,11 +4088,24 @@ func (m *QueryHasRoleRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Role |= RegistryRole(b&0x7F) << shift + 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.Approvers = append(m.Approvers, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -1469,7 +4127,7 @@ func (m *QueryHasRoleRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryHasRoleResponse) Unmarshal(dAtA []byte) error { +func (m *QueryValidateRoleChangeResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1492,15 +4150,47 @@ func (m *QueryHasRoleResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryHasRoleResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryValidateRoleChangeResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryHasRoleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryValidateRoleChangeResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", 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.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field HasRole", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Authorized", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -1517,7 +4207,7 @@ func (m *QueryHasRoleResponse) Unmarshal(dAtA []byte) error { break } } - m.HasRole = bool(v != 0) + m.Authorized = bool(v != 0) default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/registry/types/query.pb.gw.go b/x/registry/types/query.pb.gw.go index d54e834457..6da28ace7f 100644 --- a/x/registry/types/query.pb.gw.go +++ b/x/registry/types/query.pb.gw.go @@ -307,6 +307,238 @@ func local_request_Query_HasRole_0(ctx context.Context, marshaler runtime.Marsha } +func request_Query_PendingRoleChange_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPendingRoleChangeRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := client.PendingRoleChange(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_PendingRoleChange_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPendingRoleChangeRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := server.PendingRoleChange(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_PendingRoleChanges_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_PendingRoleChanges_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPendingRoleChangesRequest + 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_PendingRoleChanges_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.PendingRoleChanges(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_PendingRoleChanges_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPendingRoleChangesRequest + 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_PendingRoleChanges_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.PendingRoleChanges(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_RegistryClass_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRegistryClassRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["registry_class_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "registry_class_id") + } + + protoReq.RegistryClassId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "registry_class_id", err) + } + + msg, err := client.RegistryClass(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_RegistryClass_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRegistryClassRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["registry_class_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "registry_class_id") + } + + protoReq.RegistryClassId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "registry_class_id", err) + } + + msg, err := server.RegistryClass(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_RegistryClasses_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_RegistryClasses_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRegistryClassesRequest + 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_RegistryClasses_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.RegistryClasses(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_RegistryClasses_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRegistryClassesRequest + 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_RegistryClasses_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.RegistryClasses(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_ValidateRoleChange_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryValidateRoleChangeRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ValidateRoleChange(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ValidateRoleChange_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryValidateRoleChangeRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ValidateRoleChange(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. @@ -382,6 +614,144 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_PendingRoleChange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_PendingRoleChange_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PendingRoleChange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PendingRoleChanges_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_PendingRoleChanges_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PendingRoleChanges_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RegistryClass_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_RegistryClass_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_RegistryClass_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RegistryClasses_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_RegistryClasses_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_RegistryClasses_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_Query_ValidateRoleChange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_ValidateRoleChange_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ValidateRoleChange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -483,6 +853,126 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_PendingRoleChange_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_PendingRoleChange_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_PendingRoleChange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PendingRoleChanges_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_PendingRoleChanges_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_PendingRoleChanges_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RegistryClass_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_RegistryClass_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_RegistryClass_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RegistryClasses_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_RegistryClasses_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_RegistryClasses_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_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_Params_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_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_Query_ValidateRoleChange_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_ValidateRoleChange_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_ValidateRoleChange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -492,6 +982,18 @@ var ( pattern_Query_GetRegistries_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1}, []string{"provenance", "registry", "v1"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_HasRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5, 1, 0, 4, 1, 5, 6, 1, 0, 4, 1, 5, 7}, []string{"provenance", "registry", "v1", "has_role", "key.asset_class_id", "key.nft_id", "address", "role"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_PendingRoleChange_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"provenance", "registry", "v1", "pending_role_change", "id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_PendingRoleChanges_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"provenance", "registry", "v1", "pending_role_changes"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_RegistryClass_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"provenance", "registry", "v1", "registry_class", "registry_class_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_RegistryClasses_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"provenance", "registry", "v1", "registry_classes"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"provenance", "registry", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_ValidateRoleChange_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"provenance", "registry", "v1", "validate_role_change"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -500,4 +1002,16 @@ var ( forward_Query_GetRegistries_0 = runtime.ForwardResponseMessage forward_Query_HasRole_0 = runtime.ForwardResponseMessage + + forward_Query_PendingRoleChange_0 = runtime.ForwardResponseMessage + + forward_Query_PendingRoleChanges_0 = runtime.ForwardResponseMessage + + forward_Query_RegistryClass_0 = runtime.ForwardResponseMessage + + forward_Query_RegistryClasses_0 = runtime.ForwardResponseMessage + + forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_ValidateRoleChange_0 = runtime.ForwardResponseMessage ) diff --git a/x/registry/types/registry.pb.go b/x/registry/types/registry.pb.go index 7dd90888d4..cb92761e6e 100644 --- a/x/registry/types/registry.pb.go +++ b/x/registry/types/registry.pb.go @@ -8,15 +8,19 @@ import ( _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/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. @@ -50,26 +54,45 @@ const ( // REGISTRY_ROLE_ORIGINATOR indicates the address has originator privileges. // Originators are responsible for creating and originating the underlying assets. RegistryRole_REGISTRY_ROLE_ORIGINATOR RegistryRole = 6 + // REGISTRY_ROLE_LIEN_OWNER indicates the entity on whose behalf the registry acts as a nominal lien holder. + RegistryRole_REGISTRY_ROLE_LIEN_OWNER RegistryRole = 7 + // REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN indicates an organization with a security interest in the lien. + // This party can foreclose into the Lien Owner role or direct a transfer in case of default. + RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN RegistryRole = 8 + // REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE indicates an organization with a financial interest in the eNote. + // This party can foreclose into the Controller role or direct a transfer in case of default. + RegistryRole_REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE RegistryRole = 9 + // REGISTRY_ROLE_PLEDGEE indicates a lender or creditor that holds a security interest in pledged loans + // as collateral securing an obligation of the Pledgor. + RegistryRole_REGISTRY_ROLE_PLEDGEE RegistryRole = 10 ) var RegistryRole_name = map[int32]string{ - 0: "REGISTRY_ROLE_UNSPECIFIED", - 1: "REGISTRY_ROLE_SERVICER", - 2: "REGISTRY_ROLE_SUBSERVICER", - 3: "REGISTRY_ROLE_CONTROLLER", - 4: "REGISTRY_ROLE_CUSTODIAN", - 5: "REGISTRY_ROLE_BORROWER", - 6: "REGISTRY_ROLE_ORIGINATOR", + 0: "REGISTRY_ROLE_UNSPECIFIED", + 1: "REGISTRY_ROLE_SERVICER", + 2: "REGISTRY_ROLE_SUBSERVICER", + 3: "REGISTRY_ROLE_CONTROLLER", + 4: "REGISTRY_ROLE_CUSTODIAN", + 5: "REGISTRY_ROLE_BORROWER", + 6: "REGISTRY_ROLE_ORIGINATOR", + 7: "REGISTRY_ROLE_LIEN_OWNER", + 8: "REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN", + 9: "REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE", + 10: "REGISTRY_ROLE_PLEDGEE", } var RegistryRole_value = map[string]int32{ - "REGISTRY_ROLE_UNSPECIFIED": 0, - "REGISTRY_ROLE_SERVICER": 1, - "REGISTRY_ROLE_SUBSERVICER": 2, - "REGISTRY_ROLE_CONTROLLER": 3, - "REGISTRY_ROLE_CUSTODIAN": 4, - "REGISTRY_ROLE_BORROWER": 5, - "REGISTRY_ROLE_ORIGINATOR": 6, + "REGISTRY_ROLE_UNSPECIFIED": 0, + "REGISTRY_ROLE_SERVICER": 1, + "REGISTRY_ROLE_SUBSERVICER": 2, + "REGISTRY_ROLE_CONTROLLER": 3, + "REGISTRY_ROLE_CUSTODIAN": 4, + "REGISTRY_ROLE_BORROWER": 5, + "REGISTRY_ROLE_ORIGINATOR": 6, + "REGISTRY_ROLE_LIEN_OWNER": 7, + "REGISTRY_ROLE_SECURED_PARTY_FOR_LIEN": 8, + "REGISTRY_ROLE_SECURED_PARTY_FOR_ENOTE": 9, + "REGISTRY_ROLE_PLEDGEE": 10, } func (x RegistryRole) String() string { @@ -149,6 +172,11 @@ type RegistryEntry struct { // roles is a list of roles and addresses that can perform that role. // Each role entry contains a role type and the addresses authorized for that role. Roles []RolesEntry `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles"` + // registry_class_id is the ID of the registry class governing this entry's authorization rules. + // If set, role updates for this entry use the authorization rules defined in the referenced + // registry class. If empty, role updates fall back to the module params default policies, and + // then to legacy NFT owner authorization for any role with no policy. + RegistryClassId string `protobuf:"bytes,3,opt,name=registry_class_id,json=registryClassId,proto3" json:"registryClassId,omitempty"` } func (m *RegistryEntry) Reset() { *m = RegistryEntry{} } @@ -198,6 +226,13 @@ func (m *RegistryEntry) GetRoles() []RolesEntry { return nil } +func (m *RegistryEntry) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId + } + return "" +} + // RolesEntry represents a mapping between a role and the addresses that can perform that role. // This allows multiple addresses to be assigned the same role for a given registry entry. type RolesEntry struct { @@ -255,11 +290,166 @@ func (m *RolesEntry) GetAddresses() []string { return nil } +// RoleUpdate specifies the desired set of addresses for a single role. +type RoleUpdate struct { + // role is the role to update. + Role RegistryRole `protobuf:"varint,1,opt,name=role,proto3,enum=provenance.registry.v1.RegistryRole" json:"role,omitempty"` + // addresses is the desired set of addresses for this role. + // An empty list means the role should be cleared entirely. + Addresses []string `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses,omitempty"` +} + +func (m *RoleUpdate) Reset() { *m = RoleUpdate{} } +func (m *RoleUpdate) String() string { return proto.CompactTextString(m) } +func (*RoleUpdate) ProtoMessage() {} +func (*RoleUpdate) Descriptor() ([]byte, []int) { + return fileDescriptor_2fa7a0b4d34d0208, []int{3} +} +func (m *RoleUpdate) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RoleUpdate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RoleUpdate.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 *RoleUpdate) XXX_Merge(src proto.Message) { + xxx_messageInfo_RoleUpdate.Merge(m, src) +} +func (m *RoleUpdate) XXX_Size() int { + return m.Size() +} +func (m *RoleUpdate) XXX_DiscardUnknown() { + xxx_messageInfo_RoleUpdate.DiscardUnknown(m) +} + +var xxx_messageInfo_RoleUpdate proto.InternalMessageInfo + +func (m *RoleUpdate) GetRole() RegistryRole { + if m != nil { + return m.Role + } + return RegistryRole_REGISTRY_ROLE_UNSPECIFIED +} + +func (m *RoleUpdate) GetAddresses() []string { + if m != nil { + return m.Addresses + } + return nil +} + +// PendingRoleChange is a role change awaiting the approvals required by the affected roles' +// authorization policies. Each required party submits a single-signer approval; once the +// accumulated approvers satisfy every affected role's policy, the change is applied atomically +// and this record is removed. +type PendingRoleChange struct { + // id is the deterministic identifier of this pending change + // (a hash of key + the sorted set of role updates). + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // key identifies the registry entry the change applies to. + Key *RegistryKey `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + // role_updates is the desired state for each role the change will set when applied. The same + // desired-state, multi-role semantics as MsgSetRoles, collected through accumulated approvals. + RoleUpdates []RoleUpdate `protobuf:"bytes,3,rep,name=role_updates,json=roleUpdates,proto3" json:"role_updates"` + // proposer is the address that opened the pending change. + Proposer string `protobuf:"bytes,4,opt,name=proposer,proto3" json:"proposer,omitempty"` + // approvals is the accumulated set of addresses that have approved this change. + Approvals []string `protobuf:"bytes,5,rep,name=approvals,proto3" json:"approvals,omitempty"` + // expires_at is the block time after which this pending change is no longer valid. + // Zero value means no expiry. + ExpiresAt time.Time `protobuf:"bytes,6,opt,name=expires_at,json=expiresAt,proto3,stdtime" json:"expires_at"` +} + +func (m *PendingRoleChange) Reset() { *m = PendingRoleChange{} } +func (m *PendingRoleChange) String() string { return proto.CompactTextString(m) } +func (*PendingRoleChange) ProtoMessage() {} +func (*PendingRoleChange) Descriptor() ([]byte, []int) { + return fileDescriptor_2fa7a0b4d34d0208, []int{4} +} +func (m *PendingRoleChange) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PendingRoleChange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PendingRoleChange.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 *PendingRoleChange) XXX_Merge(src proto.Message) { + xxx_messageInfo_PendingRoleChange.Merge(m, src) +} +func (m *PendingRoleChange) XXX_Size() int { + return m.Size() +} +func (m *PendingRoleChange) XXX_DiscardUnknown() { + xxx_messageInfo_PendingRoleChange.DiscardUnknown(m) +} + +var xxx_messageInfo_PendingRoleChange proto.InternalMessageInfo + +func (m *PendingRoleChange) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *PendingRoleChange) GetKey() *RegistryKey { + if m != nil { + return m.Key + } + return nil +} + +func (m *PendingRoleChange) GetRoleUpdates() []RoleUpdate { + if m != nil { + return m.RoleUpdates + } + return nil +} + +func (m *PendingRoleChange) GetProposer() string { + if m != nil { + return m.Proposer + } + return "" +} + +func (m *PendingRoleChange) GetApprovals() []string { + if m != nil { + return m.Approvals + } + return nil +} + +func (m *PendingRoleChange) GetExpiresAt() time.Time { + if m != nil { + return m.ExpiresAt + } + return time.Time{} +} + func init() { proto.RegisterEnum("provenance.registry.v1.RegistryRole", RegistryRole_name, RegistryRole_value) proto.RegisterType((*RegistryKey)(nil), "provenance.registry.v1.RegistryKey") proto.RegisterType((*RegistryEntry)(nil), "provenance.registry.v1.RegistryEntry") proto.RegisterType((*RolesEntry)(nil), "provenance.registry.v1.RolesEntry") + proto.RegisterType((*RoleUpdate)(nil), "provenance.registry.v1.RoleUpdate") + proto.RegisterType((*PendingRoleChange)(nil), "provenance.registry.v1.PendingRoleChange") } func init() { @@ -267,37 +457,53 @@ func init() { } var fileDescriptor_2fa7a0b4d34d0208 = []byte{ - // 476 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xcd, 0x6e, 0xd3, 0x40, - 0x14, 0x85, 0xed, 0xfc, 0x49, 0x99, 0x94, 0xca, 0x1a, 0x95, 0x92, 0x04, 0x70, 0xab, 0x50, 0xa4, - 0x0a, 0xa9, 0xb6, 0x1a, 0x7e, 0x84, 0x58, 0x20, 0xc5, 0xa9, 0xa9, 0x46, 0x44, 0x71, 0x74, 0x9d, - 0x80, 0x60, 0x63, 0xa5, 0xf1, 0xd4, 0x58, 0x6d, 0x3d, 0x91, 0x67, 0x88, 0xf0, 0x86, 0x25, 0x6b, - 0x96, 0x2c, 0x79, 0x08, 0x1e, 0xa2, 0xcb, 0x8a, 0x15, 0x1b, 0x10, 0x4a, 0x5e, 0x04, 0xd9, 0x0e, - 0x71, 0x4a, 0xa8, 0xba, 0x9b, 0xb9, 0xdf, 0x39, 0x67, 0x8e, 0x46, 0x17, 0xdd, 0x1f, 0x87, 0x6c, - 0x42, 0x83, 0x61, 0x30, 0xa2, 0x7a, 0x48, 0x3d, 0x9f, 0x8b, 0x30, 0xd2, 0x27, 0xfb, 0x8b, 0xb3, - 0x36, 0x0e, 0x99, 0x60, 0x78, 0x33, 0x93, 0x69, 0x0b, 0x34, 0xd9, 0xaf, 0x6f, 0x78, 0xcc, 0x63, - 0x89, 0x44, 0x8f, 0x4f, 0xa9, 0xba, 0x5e, 0x1b, 0x31, 0x7e, 0xc6, 0xb8, 0x93, 0x82, 0xf4, 0x92, - 0xa2, 0x46, 0x0f, 0x55, 0x60, 0xee, 0x7f, 0x49, 0x23, 0x7c, 0x13, 0x95, 0x82, 0x63, 0xe1, 0xf8, - 0x6e, 0x55, 0xde, 0x96, 0x77, 0xcb, 0x50, 0x0c, 0x8e, 0x05, 0x71, 0xf1, 0x0e, 0x5a, 0x1f, 0x72, - 0x4e, 0x85, 0x33, 0x3a, 0x1d, 0x72, 0x1e, 0xe3, 0x5c, 0x82, 0xd7, 0x92, 0x69, 0x3b, 0x1e, 0x12, - 0xf7, 0x59, 0xe1, 0xcb, 0xd7, 0x2d, 0xa9, 0xf1, 0x49, 0x46, 0x37, 0xfe, 0x46, 0x9a, 0x81, 0x08, - 0x23, 0xfc, 0x18, 0xe5, 0x4f, 0x68, 0x94, 0x24, 0x56, 0x9a, 0xf7, 0xb4, 0xff, 0x57, 0xd7, 0x96, - 0x6a, 0x40, 0xac, 0xc7, 0xcf, 0x51, 0x31, 0x64, 0xa7, 0x94, 0x57, 0x73, 0xdb, 0xf9, 0xdd, 0x4a, - 0xb3, 0x71, 0xa5, 0x31, 0x16, 0x25, 0x2f, 0x19, 0x85, 0xf3, 0x5f, 0x5b, 0x12, 0xa4, 0xb6, 0xc6, - 0x47, 0x84, 0x32, 0x84, 0x9f, 0xa2, 0x42, 0x3c, 0x4e, 0x5a, 0xac, 0x37, 0x77, 0xae, 0x6b, 0x11, - 0x3b, 0x21, 0x71, 0xe0, 0x27, 0xa8, 0x3c, 0x74, 0xdd, 0x90, 0x72, 0x3e, 0xef, 0x52, 0x36, 0xaa, - 0xdf, 0xbf, 0xed, 0x6d, 0xcc, 0xff, 0xb1, 0x95, 0x32, 0x5b, 0x84, 0x7e, 0xe0, 0x41, 0x26, 0x7d, - 0xf0, 0x53, 0x46, 0x6b, 0xcb, 0x71, 0xf8, 0x2e, 0xaa, 0x81, 0x79, 0x48, 0xec, 0x3e, 0xbc, 0x71, - 0xc0, 0xea, 0x98, 0xce, 0xa0, 0x6b, 0xf7, 0xcc, 0x36, 0x79, 0x41, 0xcc, 0x03, 0x45, 0xc2, 0x75, - 0xb4, 0x79, 0x19, 0xdb, 0x26, 0xbc, 0x22, 0x6d, 0x13, 0x14, 0x79, 0xd5, 0x6a, 0x0f, 0x8c, 0x05, - 0xce, 0xe1, 0x3b, 0xa8, 0x7a, 0x19, 0xb7, 0xad, 0x6e, 0x1f, 0xac, 0x4e, 0xc7, 0x04, 0x25, 0x8f, - 0x6f, 0xa3, 0x5b, 0xff, 0xd0, 0x81, 0xdd, 0xb7, 0x0e, 0x48, 0xab, 0xab, 0x14, 0x56, 0x5f, 0x35, - 0x2c, 0x00, 0xeb, 0xb5, 0x09, 0x4a, 0x71, 0x35, 0xd6, 0x02, 0x72, 0x48, 0xba, 0xad, 0xbe, 0x05, - 0x4a, 0xc9, 0x38, 0x39, 0x9f, 0xaa, 0xf2, 0xc5, 0x54, 0x95, 0x7f, 0x4f, 0x55, 0xf9, 0xf3, 0x4c, - 0x95, 0x2e, 0x66, 0xaa, 0xf4, 0x63, 0xa6, 0x4a, 0xa8, 0xe6, 0xb3, 0x2b, 0xfe, 0xb7, 0x27, 0xbf, - 0x7d, 0xe4, 0xf9, 0xe2, 0xdd, 0xfb, 0x23, 0x6d, 0xc4, 0xce, 0xf4, 0x4c, 0xb4, 0xe7, 0xb3, 0xa5, - 0x9b, 0xfe, 0x21, 0x5b, 0x7e, 0x11, 0x8d, 0x29, 0x3f, 0x2a, 0x25, 0xeb, 0xfa, 0xf0, 0x4f, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x4f, 0x36, 0x83, 0x50, 0x20, 0x03, 0x00, 0x00, + // 721 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x54, 0x4f, 0x4f, 0xdb, 0x48, + 0x1c, 0x8d, 0x9d, 0x3f, 0x4b, 0x26, 0x2c, 0x6b, 0x46, 0xc0, 0x3a, 0xd9, 0x25, 0x41, 0x59, 0x90, + 0xd8, 0xd5, 0xe2, 0x08, 0x96, 0xad, 0xaa, 0x1e, 0x2a, 0xe5, 0xcf, 0x80, 0x2c, 0xa2, 0x38, 0x9a, + 0x24, 0x45, 0xf4, 0x62, 0x99, 0x78, 0x30, 0x16, 0x89, 0xc7, 0xf2, 0x0c, 0x88, 0x5c, 0xfa, 0x19, + 0x38, 0xf6, 0xd8, 0x0f, 0xd1, 0x0f, 0xc1, 0x91, 0xf6, 0x54, 0xf5, 0x40, 0x2b, 0xb8, 0xb5, 0x5f, + 0xa2, 0xb2, 0x1d, 0x27, 0x40, 0x8a, 0xa2, 0x9e, 0x7a, 0xf3, 0xfc, 0xde, 0xfb, 0xcd, 0xfb, 0xbd, + 0x79, 0x33, 0x06, 0x6b, 0xae, 0x47, 0xcf, 0x88, 0x63, 0x38, 0x5d, 0x52, 0xf2, 0x88, 0x65, 0x33, + 0xee, 0x0d, 0x4a, 0x67, 0x9b, 0xa3, 0x6f, 0xc5, 0xf5, 0x28, 0xa7, 0x70, 0x69, 0x4c, 0x53, 0x46, + 0xd0, 0xd9, 0x66, 0x6e, 0xc1, 0xa2, 0x16, 0x0d, 0x28, 0x25, 0xff, 0x2b, 0x64, 0xe7, 0xb2, 0x5d, + 0xca, 0xfa, 0x94, 0xe9, 0x21, 0x10, 0x2e, 0x86, 0x50, 0xc1, 0xa2, 0xd4, 0xea, 0x91, 0x52, 0xb0, + 0x3a, 0x3c, 0x3d, 0x2a, 0x71, 0xbb, 0x4f, 0x18, 0x37, 0xfa, 0x6e, 0x48, 0x28, 0x36, 0x41, 0x06, + 0x0f, 0x05, 0xf6, 0xc8, 0x00, 0x2e, 0x82, 0x94, 0x73, 0xc4, 0x75, 0xdb, 0x94, 0x85, 0x15, 0x61, + 0x3d, 0x8d, 0x93, 0xce, 0x11, 0x57, 0x4d, 0xb8, 0x0a, 0xe6, 0x0c, 0xc6, 0x08, 0xd7, 0xbb, 0x3d, + 0x83, 0x31, 0x1f, 0x16, 0x03, 0x78, 0x36, 0xa8, 0x56, 0xfd, 0xa2, 0x6a, 0x3e, 0x4b, 0xbc, 0x7e, + 0x53, 0x88, 0x15, 0xdf, 0x09, 0xe0, 0xd7, 0x68, 0x4b, 0xe4, 0x70, 0x6f, 0x00, 0xff, 0x07, 0xf1, + 0x13, 0x32, 0x08, 0x76, 0xcc, 0x6c, 0xfd, 0xa5, 0x7c, 0xdf, 0x9b, 0x72, 0x67, 0x0c, 0xec, 0xf3, + 0xe1, 0x73, 0x90, 0xf4, 0x68, 0x8f, 0x30, 0x59, 0x5c, 0x89, 0xaf, 0x67, 0xb6, 0x8a, 0x8f, 0x36, + 0xfa, 0xa4, 0x40, 0xa9, 0x92, 0xb8, 0xbc, 0x2e, 0xc4, 0x70, 0xd8, 0x06, 0x55, 0x30, 0x1f, 0xd1, + 0xc6, 0x73, 0xc7, 0xfd, 0xb9, 0x2b, 0xcb, 0x5f, 0xae, 0x0b, 0xd9, 0x08, 0x1c, 0x8e, 0xff, 0x2f, + 0xed, 0xdb, 0x9c, 0xf4, 0x5d, 0x3e, 0xc0, 0xbf, 0x3d, 0x80, 0x8a, 0xaf, 0x00, 0x18, 0xab, 0xc0, + 0xa7, 0x20, 0xe1, 0x2b, 0x04, 0x86, 0xe6, 0xb6, 0x56, 0xa7, 0x19, 0xf2, 0x3b, 0x71, 0xd0, 0x01, + 0x9f, 0x80, 0xb4, 0x61, 0x9a, 0x1e, 0x61, 0x6c, 0x68, 0x2b, 0x5d, 0x91, 0xdf, 0xbf, 0xdd, 0x58, + 0x18, 0x66, 0x56, 0x0e, 0xb1, 0x16, 0xf7, 0x6c, 0xc7, 0xc2, 0x63, 0x6a, 0xa4, 0xdf, 0x71, 0x4d, + 0x83, 0x93, 0x9f, 0xa0, 0xff, 0x51, 0x04, 0xf3, 0x4d, 0xe2, 0x98, 0x7e, 0x99, 0xf6, 0x48, 0xf5, + 0xd8, 0x70, 0x2c, 0x02, 0xe7, 0x80, 0x38, 0xba, 0x28, 0xa2, 0x6d, 0x46, 0x39, 0x8b, 0x3f, 0x98, + 0xf3, 0x1e, 0x98, 0xf5, 0x87, 0xd3, 0x4f, 0x03, 0x77, 0x4c, 0x8e, 0x4f, 0x8f, 0x3b, 0x3c, 0x88, + 0x61, 0xdc, 0x19, 0x6f, 0x54, 0x61, 0x70, 0x1b, 0xcc, 0xb8, 0x1e, 0x75, 0x29, 0x23, 0x9e, 0x9c, + 0x08, 0xb2, 0x7e, 0xdc, 0xe0, 0x88, 0x19, 0x9c, 0x8b, 0xeb, 0xeb, 0x19, 0x3d, 0x26, 0x27, 0xa7, + 0x9e, 0x4b, 0x44, 0x85, 0x55, 0x00, 0xc8, 0xb9, 0x6b, 0x7b, 0x84, 0xe9, 0x06, 0x97, 0x53, 0x81, + 0xf1, 0x9c, 0x12, 0xbe, 0x39, 0x25, 0x7a, 0x73, 0x4a, 0x3b, 0x7a, 0x73, 0x95, 0x19, 0x7f, 0xe0, + 0x8b, 0x4f, 0x05, 0x01, 0xa7, 0x87, 0x7d, 0x65, 0xfe, 0xcf, 0x57, 0x11, 0xcc, 0xde, 0xcd, 0x0a, + 0x2e, 0x83, 0x2c, 0x46, 0xbb, 0x6a, 0xab, 0x8d, 0x0f, 0x74, 0xac, 0xd5, 0x91, 0xde, 0x69, 0xb4, + 0x9a, 0xa8, 0xaa, 0xee, 0xa8, 0xa8, 0x26, 0xc5, 0x60, 0x0e, 0x2c, 0xdd, 0x87, 0x5b, 0x08, 0xbf, + 0x50, 0xab, 0x08, 0x4b, 0xc2, 0x64, 0x6b, 0xab, 0x53, 0x19, 0xc1, 0x22, 0xfc, 0x13, 0xc8, 0xf7, + 0xe1, 0xaa, 0xd6, 0x68, 0x63, 0xad, 0x5e, 0x47, 0x58, 0x8a, 0xc3, 0x3f, 0xc0, 0xef, 0x0f, 0xd0, + 0x4e, 0xab, 0xad, 0xd5, 0xd4, 0x72, 0x43, 0x4a, 0x4c, 0xaa, 0x56, 0x34, 0x8c, 0xb5, 0x7d, 0x84, + 0xa5, 0xe4, 0xe4, 0xb6, 0x1a, 0x56, 0x77, 0xd5, 0x46, 0xb9, 0xad, 0x61, 0x29, 0x35, 0x89, 0xd6, + 0x55, 0xd4, 0xd0, 0xb5, 0xfd, 0x06, 0xc2, 0xd2, 0x2f, 0x70, 0x1d, 0xac, 0x3e, 0x74, 0x53, 0xed, + 0x60, 0x54, 0xd3, 0x9b, 0x65, 0xdc, 0x3e, 0xd0, 0x77, 0x34, 0x1c, 0xf0, 0xa5, 0x19, 0xf8, 0x37, + 0x58, 0x9b, 0xc6, 0x44, 0x0d, 0xad, 0x8d, 0xa4, 0x34, 0xcc, 0x82, 0xc5, 0xfb, 0xd4, 0x66, 0x1d, + 0xd5, 0x76, 0x11, 0x92, 0x40, 0xe5, 0xe4, 0xf2, 0x26, 0x2f, 0x5c, 0xdd, 0xe4, 0x85, 0xcf, 0x37, + 0x79, 0xe1, 0xe2, 0x36, 0x1f, 0xbb, 0xba, 0xcd, 0xc7, 0x3e, 0xdc, 0xe6, 0x63, 0x20, 0x6b, 0xd3, + 0x47, 0xee, 0x5c, 0x53, 0x78, 0xb9, 0x6d, 0xd9, 0xfc, 0xf8, 0xf4, 0x50, 0xe9, 0xd2, 0x7e, 0x69, + 0x4c, 0xda, 0xb0, 0xe9, 0x9d, 0x55, 0xe9, 0x7c, 0xfc, 0x4f, 0xe7, 0x03, 0x97, 0xb0, 0xc3, 0x54, + 0x70, 0x07, 0xfe, 0xfb, 0x16, 0x00, 0x00, 0xff, 0xff, 0x76, 0x19, 0x01, 0x7c, 0xf7, 0x05, 0x00, + 0x00, } func (m *RegistryKey) Marshal() (dAtA []byte, err error) { @@ -357,6 +563,13 @@ func (m *RegistryEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintRegistry(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0x1a + } if len(m.Roles) > 0 { for iNdEx := len(m.Roles) - 1; iNdEx >= 0; iNdEx-- { { @@ -423,6 +636,123 @@ func (m *RolesEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *RoleUpdate) 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 *RoleUpdate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoleUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Addresses) > 0 { + for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Addresses[iNdEx]) + copy(dAtA[i:], m.Addresses[iNdEx]) + i = encodeVarintRegistry(dAtA, i, uint64(len(m.Addresses[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if m.Role != 0 { + i = encodeVarintRegistry(dAtA, i, uint64(m.Role)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *PendingRoleChange) 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 *PendingRoleChange) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PendingRoleChange) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n2, err2 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.ExpiresAt, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.ExpiresAt):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintRegistry(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x32 + if len(m.Approvals) > 0 { + for iNdEx := len(m.Approvals) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Approvals[iNdEx]) + copy(dAtA[i:], m.Approvals[iNdEx]) + i = encodeVarintRegistry(dAtA, i, uint64(len(m.Approvals[iNdEx]))) + i-- + dAtA[i] = 0x2a + } + } + if len(m.Proposer) > 0 { + i -= len(m.Proposer) + copy(dAtA[i:], m.Proposer) + i = encodeVarintRegistry(dAtA, i, uint64(len(m.Proposer))) + i-- + dAtA[i] = 0x22 + } + if len(m.RoleUpdates) > 0 { + for iNdEx := len(m.RoleUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoleUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintRegistry(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.Key != nil { + { + size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintRegistry(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintRegistry(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintRegistry(dAtA []byte, offset int, v uint64) int { offset -= sovRegistry(v) base := offset @@ -467,6 +797,10 @@ func (m *RegistryEntry) Size() (n int) { n += 1 + l + sovRegistry(uint64(l)) } } + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovRegistry(uint64(l)) + } return n } @@ -488,6 +822,59 @@ func (m *RolesEntry) Size() (n int) { return n } +func (m *RoleUpdate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Role != 0 { + n += 1 + sovRegistry(uint64(m.Role)) + } + if len(m.Addresses) > 0 { + for _, s := range m.Addresses { + l = len(s) + n += 1 + l + sovRegistry(uint64(l)) + } + } + return n +} + +func (m *PendingRoleChange) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + sovRegistry(uint64(l)) + } + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovRegistry(uint64(l)) + } + if len(m.RoleUpdates) > 0 { + for _, e := range m.RoleUpdates { + l = e.Size() + n += 1 + l + sovRegistry(uint64(l)) + } + } + l = len(m.Proposer) + if l > 0 { + n += 1 + l + sovRegistry(uint64(l)) + } + if len(m.Approvals) > 0 { + for _, s := range m.Approvals { + l = len(s) + n += 1 + l + sovRegistry(uint64(l)) + } + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.ExpiresAt) + n += 1 + l + sovRegistry(uint64(l)) + return n +} + func sovRegistry(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -707,6 +1094,38 @@ func (m *RegistryEntry) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRegistry + } + 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 ErrInvalidLengthRegistry + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRegistry + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RegistryClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRegistry(dAtA[iNdEx:]) @@ -829,6 +1248,356 @@ func (m *RolesEntry) Unmarshal(dAtA []byte) error { } return nil } +func (m *RoleUpdate) 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 ErrIntOverflowRegistry + } + 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: RoleUpdate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RoleUpdate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + } + m.Role = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRegistry + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Role |= RegistryRole(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRegistry + } + 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 ErrInvalidLengthRegistry + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRegistry + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRegistry(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthRegistry + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PendingRoleChange) 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 ErrIntOverflowRegistry + } + 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: PendingRoleChange: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PendingRoleChange: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRegistry + } + 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 ErrInvalidLengthRegistry + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRegistry + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRegistry + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRegistry + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRegistry + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RoleUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRegistry + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRegistry + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRegistry + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RoleUpdates = append(m.RoleUpdates, RoleUpdate{}) + if err := m.RoleUpdates[len(m.RoleUpdates)-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 Proposer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRegistry + } + 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 ErrInvalidLengthRegistry + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRegistry + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proposer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Approvals", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRegistry + } + 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 ErrInvalidLengthRegistry + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRegistry + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Approvals = append(m.Approvals, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpiresAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRegistry + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRegistry + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRegistry + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.ExpiresAt, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRegistry(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthRegistry + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipRegistry(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/registry/types/tx.pb.go b/x/registry/types/tx.pb.go index 4074e10e09..e6241fd210 100644 --- a/x/registry/types/tx.pb.go +++ b/x/registry/types/tx.pb.go @@ -42,6 +42,9 @@ type MsgRegisterNFT struct { // roles is a list of roles and addresses that can perform that role. // Each role entry defines a role type and the addresses authorized for that role. Roles []RolesEntry `protobuf:"bytes,3,rep,name=roles,proto3" json:"roles"` + // registry_class_id optionally associates the new registry entry with a registry class whose + // authorization rules govern subsequent role updates. If set, the referenced class must exist. + RegistryClassId string `protobuf:"bytes,4,opt,name=registry_class_id,json=registryClassId,proto3" json:"registryClassId,omitempty"` } func (m *MsgRegisterNFT) Reset() { *m = MsgRegisterNFT{} } @@ -98,6 +101,13 @@ func (m *MsgRegisterNFT) GetRoles() []RolesEntry { return nil } +func (m *MsgRegisterNFT) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId + } + return "" +} + // MsgRegisterNFTResponse defines the response for RegisterNFT. // This is an empty response indicating successful registration. type MsgRegisterNFTResponse struct { @@ -139,8 +149,9 @@ var xxx_messageInfo_MsgRegisterNFTResponse proto.InternalMessageInfo // MsgGrantRole represents a message to grant a role to one or more addresses. // This message adds the specified addresses to an existing role for the given registry key. type MsgGrantRole struct { - // signer is the address that is authorized to grant the role. - // This address must have the appropriate permissions to modify role assignments. + // signer is the address authorizing the role grant. The signer must satisfy the role's + // authorization policy on its own (e.g. the NFT owner for roles without a policy). Multi-party + // role changes are made through ProposeRoleChange / ApproveRoleChange instead. Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` // key is the registry key to grant the role to. // This identifies the specific registry entry to modify. @@ -255,8 +266,9 @@ var xxx_messageInfo_MsgGrantRoleResponse proto.InternalMessageInfo // MsgRevokeRole represents a message to revoke a role from one or more addresses. // This message removes the specified addresses from an existing role for the given registry key. type MsgRevokeRole struct { - // signer is the address that is authorized to revoke the role. - // This address must have the appropriate permissions to modify role assignments. + // signer is the address authorizing the role revocation. The signer must satisfy the role's + // authorization policy on its own (e.g. the NFT owner for roles without a policy). Multi-party + // role changes are made through ProposeRoleChange / ApproveRoleChange instead. Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` // key is the registry key to revoke the role from. // This identifies the specific registry entry to modify. @@ -560,852 +572,4537 @@ func (m *MsgRegistryBulkUpdateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgRegistryBulkUpdateResponse proto.InternalMessageInfo -func init() { - proto.RegisterType((*MsgRegisterNFT)(nil), "provenance.registry.v1.MsgRegisterNFT") - proto.RegisterType((*MsgRegisterNFTResponse)(nil), "provenance.registry.v1.MsgRegisterNFTResponse") - proto.RegisterType((*MsgGrantRole)(nil), "provenance.registry.v1.MsgGrantRole") - proto.RegisterType((*MsgGrantRoleResponse)(nil), "provenance.registry.v1.MsgGrantRoleResponse") - proto.RegisterType((*MsgRevokeRole)(nil), "provenance.registry.v1.MsgRevokeRole") - proto.RegisterType((*MsgRevokeRoleResponse)(nil), "provenance.registry.v1.MsgRevokeRoleResponse") - proto.RegisterType((*MsgUnregisterNFT)(nil), "provenance.registry.v1.MsgUnregisterNFT") - proto.RegisterType((*MsgUnregisterNFTResponse)(nil), "provenance.registry.v1.MsgUnregisterNFTResponse") - proto.RegisterType((*MsgRegistryBulkUpdate)(nil), "provenance.registry.v1.MsgRegistryBulkUpdate") - proto.RegisterType((*MsgRegistryBulkUpdateResponse)(nil), "provenance.registry.v1.MsgRegistryBulkUpdateResponse") +// MsgSetRoles atomically sets the desired state for one or more roles on a registry entry. +// For each role in role_updates, the keeper computes the diff between current and desired +// addresses and applies grants and revokes to reach the desired state. +// All updates succeed or all fail (atomic). +type MsgSetRoles struct { + // signer is the address authorizing the role updates. The signer must satisfy each affected + // role's authorization policy on its own. Multi-party role changes are made through + // ProposeRoleChange / ApproveRoleChange instead. + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + // key identifies the registry entry to update. + Key *RegistryKey `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + // role_updates contains the desired state for each role to update. + // At least one entry is required. Roles not listed here are unchanged. + RoleUpdates []RoleUpdate `protobuf:"bytes,3,rep,name=role_updates,json=roleUpdates,proto3" json:"role_updates"` } -func init() { proto.RegisterFile("provenance/registry/v1/tx.proto", fileDescriptor_afab3f18b6d8353c) } - -var fileDescriptor_afab3f18b6d8353c = []byte{ - // 587 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x95, 0x3d, 0x6f, 0xd3, 0x40, - 0x18, 0xc7, 0x73, 0x75, 0x5a, 0xd4, 0x27, 0xb4, 0x42, 0x56, 0x48, 0x5d, 0x4b, 0x38, 0x51, 0x68, - 0x50, 0x54, 0x11, 0xbb, 0x0d, 0x14, 0x21, 0x06, 0x24, 0x22, 0x15, 0x06, 0x14, 0x84, 0x0c, 0x5d, - 0x58, 0xaa, 0xbc, 0x9c, 0x0e, 0x2b, 0x8d, 0x2f, 0xba, 0xbb, 0x46, 0x35, 0x13, 0x62, 0x62, 0xe4, - 0x0b, 0x30, 0xf0, 0x0d, 0x3a, 0xf0, 0x19, 0x50, 0xc7, 0x8a, 0x89, 0x09, 0xa1, 0x64, 0xe8, 0x37, - 0x80, 0x15, 0xf9, 0xdd, 0x46, 0x79, 0x83, 0x01, 0x06, 0x36, 0x5f, 0xee, 0xf7, 0xdc, 0xff, 0xff, - 0x7f, 0xe2, 0xc7, 0x07, 0xc5, 0x01, 0xa3, 0x43, 0x6c, 0xb7, 0xec, 0x0e, 0x36, 0x18, 0x26, 0x16, - 0x17, 0xcc, 0x31, 0x86, 0xbb, 0x86, 0x38, 0xd1, 0x07, 0x8c, 0x0a, 0x2a, 0x17, 0x62, 0x40, 0x0f, - 0x01, 0x7d, 0xb8, 0xab, 0xe6, 0x09, 0x25, 0xd4, 0x43, 0x0c, 0xf7, 0xc9, 0xa7, 0xd5, 0xcd, 0x0e, - 0xe5, 0x7d, 0xca, 0x0f, 0xfd, 0x0d, 0x7f, 0x11, 0x6c, 0x6d, 0xf8, 0x2b, 0xa3, 0xcf, 0x89, 0x2b, - 0xd0, 0xe7, 0x24, 0xd8, 0xa8, 0x4c, 0xb1, 0x10, 0xa9, 0x79, 0x58, 0xf9, 0x13, 0x82, 0xf5, 0x26, - 0x27, 0xa6, 0xf7, 0x2b, 0x66, 0x4f, 0x1e, 0x3e, 0x97, 0x77, 0x60, 0x85, 0x5b, 0xc4, 0xc6, 0x4c, - 0x41, 0x25, 0x54, 0x5d, 0x6d, 0x28, 0x9f, 0x3f, 0xd6, 0xf2, 0x81, 0xe8, 0x83, 0x6e, 0x97, 0x61, - 0xce, 0x9f, 0x09, 0x66, 0xd9, 0xc4, 0x0c, 0x38, 0x79, 0x0f, 0xa4, 0x1e, 0x76, 0x94, 0xa5, 0x12, - 0xaa, 0xe6, 0xea, 0xd7, 0xf5, 0xc9, 0xd9, 0x74, 0x33, 0x78, 0x7e, 0x8c, 0x1d, 0xd3, 0xe5, 0xe5, - 0xfb, 0xb0, 0xcc, 0xe8, 0x11, 0xe6, 0x8a, 0x54, 0x92, 0xaa, 0xb9, 0x7a, 0x79, 0x6a, 0xa1, 0x0b, - 0xed, 0xdb, 0x82, 0x39, 0x8d, 0xec, 0xd9, 0xd7, 0x62, 0xc6, 0xf4, 0xcb, 0xee, 0xe5, 0xde, 0x5c, - 0x9c, 0x6e, 0x07, 0x1e, 0xca, 0x0a, 0x14, 0xd2, 0x39, 0x4c, 0xcc, 0x07, 0xd4, 0xe6, 0xb8, 0xfc, - 0x1d, 0xc1, 0xe5, 0x26, 0x27, 0x8f, 0x58, 0xcb, 0x16, 0xee, 0x51, 0x7f, 0x2f, 0xe0, 0x5d, 0xc8, - 0xba, 0x4e, 0x15, 0xa9, 0x84, 0xaa, 0xeb, 0xf5, 0xad, 0x79, 0x75, 0xae, 0x39, 0xd3, 0xab, 0x90, - 0xef, 0xc0, 0x6a, 0xcb, 0x77, 0x82, 0xb9, 0x92, 0x2d, 0x49, 0x33, 0x5d, 0xc6, 0x68, 0xba, 0x25, - 0x05, 0xc8, 0x27, 0x73, 0x47, 0x0d, 0xf9, 0x81, 0x60, 0xcd, 0xeb, 0xd5, 0x90, 0xf6, 0xf0, 0x7f, - 0xd5, 0x91, 0x0d, 0xb8, 0x9a, 0x0a, 0x1e, 0xb5, 0xe4, 0x2d, 0x82, 0x2b, 0x4d, 0x4e, 0x0e, 0x6c, - 0xf6, 0x0f, 0x06, 0x21, 0xed, 0x51, 0x05, 0xe5, 0x57, 0x27, 0x91, 0xcd, 0xf7, 0x28, 0x08, 0xe0, - 0x1f, 0xd0, 0x38, 0x3e, 0xea, 0x1d, 0x0c, 0xba, 0x2d, 0xf1, 0x27, 0xff, 0xe0, 0x3e, 0x5c, 0xc2, - 0xb6, 0x60, 0x16, 0xe6, 0xca, 0x92, 0x37, 0x7f, 0x95, 0x79, 0x7e, 0x93, 0x23, 0x18, 0xd6, 0xa6, - 0xbd, 0x17, 0xe1, 0xda, 0x44, 0x7b, 0x61, 0x80, 0xfa, 0x87, 0x2c, 0x48, 0x4d, 0x4e, 0x64, 0x0c, - 0xb9, 0xe4, 0x27, 0xe7, 0xc6, 0x34, 0xe9, 0xf4, 0x48, 0xab, 0xfa, 0x62, 0x5c, 0x28, 0x27, 0x1f, - 0xc2, 0x6a, 0x3c, 0xf6, 0x5b, 0x33, 0x8a, 0x23, 0x4a, 0xbd, 0xb9, 0x08, 0x15, 0x09, 0xb4, 0x01, - 0x12, 0x63, 0x54, 0x99, 0x69, 0x2f, 0xc4, 0xd4, 0xda, 0x42, 0x58, 0xa4, 0xd1, 0x83, 0xb5, 0xf4, - 0x7b, 0x59, 0x9d, 0x51, 0x9f, 0x22, 0xd5, 0x9d, 0x45, 0xc9, 0x48, 0xec, 0x15, 0xc8, 0x13, 0xde, - 0xae, 0xda, 0xdc, 0xbe, 0x27, 0x71, 0x75, 0xef, 0xb7, 0xf0, 0x50, 0x5b, 0x5d, 0x7e, 0x7d, 0x71, - 0xba, 0x8d, 0x1a, 0xbd, 0xb3, 0x91, 0x86, 0xce, 0x47, 0x1a, 0xfa, 0x36, 0xd2, 0xd0, 0xbb, 0xb1, - 0x96, 0x39, 0x1f, 0x6b, 0x99, 0x2f, 0x63, 0x2d, 0x03, 0x9b, 0x16, 0x9d, 0x72, 0xf2, 0x53, 0xf4, - 0xe2, 0x36, 0xb1, 0xc4, 0xcb, 0xe3, 0xb6, 0xde, 0xa1, 0x7d, 0x23, 0x86, 0x6a, 0x16, 0x4d, 0xac, - 0x8c, 0x93, 0xf8, 0x2e, 0x14, 0xce, 0x00, 0xf3, 0xf6, 0x8a, 0x77, 0x0d, 0xde, 0xfa, 0x19, 0x00, - 0x00, 0xff, 0xff, 0x14, 0x84, 0xbd, 0x73, 0xb2, 0x07, 0x00, 0x00, +func (m *MsgSetRoles) Reset() { *m = MsgSetRoles{} } +func (m *MsgSetRoles) String() string { return proto.CompactTextString(m) } +func (*MsgSetRoles) ProtoMessage() {} +func (*MsgSetRoles) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{10} +} +func (m *MsgSetRoles) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetRoles) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetRoles.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 *MsgSetRoles) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetRoles.Merge(m, src) +} +func (m *MsgSetRoles) XXX_Size() int { + return m.Size() +} +func (m *MsgSetRoles) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetRoles.DiscardUnknown(m) } -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn +var xxx_messageInfo_MsgSetRoles proto.InternalMessageInfo -// 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 +func (m *MsgSetRoles) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} -// 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 { - // RegisterNFT registers a new NFT in the registry. - // This creates a new registry entry with the specified roles and addresses. - RegisterNFT(ctx context.Context, in *MsgRegisterNFT, opts ...grpc.CallOption) (*MsgRegisterNFTResponse, error) - // GrantRole grants a role to one or more addresses. - // This adds the specified addresses to the role for the given registry key. - GrantRole(ctx context.Context, in *MsgGrantRole, opts ...grpc.CallOption) (*MsgGrantRoleResponse, error) - // RevokeRole revokes a role from one or more addresses. - // This removes the specified addresses from the role for the given registry key. - RevokeRole(ctx context.Context, in *MsgRevokeRole, opts ...grpc.CallOption) (*MsgRevokeRoleResponse, error) - // UnregisterNFT unregisters an NFT from the registry. - // This removes the entire registry entry for the specified key. - UnregisterNFT(ctx context.Context, in *MsgUnregisterNFT, opts ...grpc.CallOption) (*MsgUnregisterNFTResponse, error) - // RegistryBulkUpdate registers, or updates, multiple NFTs in the registry. - // This creates multiple registry entries, or updates if one exists. - // Each registry in this will cost one MsgRegisterNFT. - RegistryBulkUpdate(ctx context.Context, in *MsgRegistryBulkUpdate, opts ...grpc.CallOption) (*MsgRegistryBulkUpdateResponse, error) +func (m *MsgSetRoles) GetKey() *RegistryKey { + if m != nil { + return m.Key + } + return nil } -type msgClient struct { - cc grpc1.ClientConn +func (m *MsgSetRoles) GetRoleUpdates() []RoleUpdate { + if m != nil { + return m.RoleUpdates + } + return nil } -func NewMsgClient(cc grpc1.ClientConn) MsgClient { - return &msgClient{cc} +// MsgSetRolesResponse defines the response for SetRoles. +type MsgSetRolesResponse struct { } -func (c *msgClient) RegisterNFT(ctx context.Context, in *MsgRegisterNFT, opts ...grpc.CallOption) (*MsgRegisterNFTResponse, error) { - out := new(MsgRegisterNFTResponse) - err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/RegisterNFT", in, out, opts...) - if err != nil { - return nil, err +func (m *MsgSetRolesResponse) Reset() { *m = MsgSetRolesResponse{} } +func (m *MsgSetRolesResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSetRolesResponse) ProtoMessage() {} +func (*MsgSetRolesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{11} +} +func (m *MsgSetRolesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetRolesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetRolesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - return out, nil +} +func (m *MsgSetRolesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetRolesResponse.Merge(m, src) +} +func (m *MsgSetRolesResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSetRolesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetRolesResponse.DiscardUnknown(m) } -func (c *msgClient) GrantRole(ctx context.Context, in *MsgGrantRole, opts ...grpc.CallOption) (*MsgGrantRoleResponse, error) { - out := new(MsgGrantRoleResponse) - err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/GrantRole", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil +var xxx_messageInfo_MsgSetRolesResponse proto.InternalMessageInfo + +// MsgProposeRoleChange opens a pending role change that collects single-signer approvals until +// every affected role's authorization policy is satisfied, then applies the whole batch +// atomically. Its payload mirrors MsgSetRoles (desired-state, multi-role), but using single-signer +// messages (rather than one multi-signer message) keeps every step compatible with authz delegation. +type MsgProposeRoleChange struct { + // signer is the address proposing the change. It is recorded as the first approval; it only + // counts toward a policy if the signer is itself a required party. + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + // key identifies the registry entry to change. + Key *RegistryKey `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + // role_updates contains the desired state for each role to set when the change is applied. + // At least one entry is required. Roles not listed here are unchanged. + RoleUpdates []RoleUpdate `protobuf:"bytes,3,rep,name=role_updates,json=roleUpdates,proto3" json:"role_updates"` } -func (c *msgClient) RevokeRole(ctx context.Context, in *MsgRevokeRole, opts ...grpc.CallOption) (*MsgRevokeRoleResponse, error) { - out := new(MsgRevokeRoleResponse) - err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/RevokeRole", in, out, opts...) - if err != nil { - return nil, err +func (m *MsgProposeRoleChange) Reset() { *m = MsgProposeRoleChange{} } +func (m *MsgProposeRoleChange) String() string { return proto.CompactTextString(m) } +func (*MsgProposeRoleChange) ProtoMessage() {} +func (*MsgProposeRoleChange) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{12} +} +func (m *MsgProposeRoleChange) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgProposeRoleChange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgProposeRoleChange.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - return out, nil +} +func (m *MsgProposeRoleChange) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgProposeRoleChange.Merge(m, src) +} +func (m *MsgProposeRoleChange) XXX_Size() int { + return m.Size() +} +func (m *MsgProposeRoleChange) XXX_DiscardUnknown() { + xxx_messageInfo_MsgProposeRoleChange.DiscardUnknown(m) } -func (c *msgClient) UnregisterNFT(ctx context.Context, in *MsgUnregisterNFT, opts ...grpc.CallOption) (*MsgUnregisterNFTResponse, error) { - out := new(MsgUnregisterNFTResponse) - err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/UnregisterNFT", in, out, opts...) - if err != nil { - return nil, err +var xxx_messageInfo_MsgProposeRoleChange proto.InternalMessageInfo + +func (m *MsgProposeRoleChange) GetSigner() string { + if m != nil { + return m.Signer } - return out, nil + return "" } -func (c *msgClient) RegistryBulkUpdate(ctx context.Context, in *MsgRegistryBulkUpdate, opts ...grpc.CallOption) (*MsgRegistryBulkUpdateResponse, error) { - out := new(MsgRegistryBulkUpdateResponse) - err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/RegistryBulkUpdate", in, out, opts...) - if err != nil { - return nil, err +func (m *MsgProposeRoleChange) GetKey() *RegistryKey { + if m != nil { + return m.Key } - return out, nil + return nil } -// MsgServer is the server API for Msg service. -type MsgServer interface { - // RegisterNFT registers a new NFT in the registry. - // This creates a new registry entry with the specified roles and addresses. - RegisterNFT(context.Context, *MsgRegisterNFT) (*MsgRegisterNFTResponse, error) - // GrantRole grants a role to one or more addresses. - // This adds the specified addresses to the role for the given registry key. - GrantRole(context.Context, *MsgGrantRole) (*MsgGrantRoleResponse, error) - // RevokeRole revokes a role from one or more addresses. - // This removes the specified addresses from the role for the given registry key. - RevokeRole(context.Context, *MsgRevokeRole) (*MsgRevokeRoleResponse, error) - // UnregisterNFT unregisters an NFT from the registry. - // This removes the entire registry entry for the specified key. - UnregisterNFT(context.Context, *MsgUnregisterNFT) (*MsgUnregisterNFTResponse, error) - // RegistryBulkUpdate registers, or updates, multiple NFTs in the registry. - // This creates multiple registry entries, or updates if one exists. - // Each registry in this will cost one MsgRegisterNFT. - RegistryBulkUpdate(context.Context, *MsgRegistryBulkUpdate) (*MsgRegistryBulkUpdateResponse, error) +func (m *MsgProposeRoleChange) GetRoleUpdates() []RoleUpdate { + if m != nil { + return m.RoleUpdates + } + return nil } -// UnimplementedMsgServer can be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct { +// MsgProposeRoleChangeResponse defines the response for ProposeRoleChange. +type MsgProposeRoleChangeResponse struct { + // change_id is the deterministic identifier of the pending change. It is also returned when the + // change auto-applied immediately (e.g. a single-party policy satisfied by the proposer). + ChangeId string `protobuf:"bytes,1,opt,name=change_id,json=changeId,proto3" json:"change_id,omitempty"` + // applied is true if the proposal alone satisfied the policy and the change was applied. + Applied bool `protobuf:"varint,2,opt,name=applied,proto3" json:"applied,omitempty"` } -func (*UnimplementedMsgServer) RegisterNFT(ctx context.Context, req *MsgRegisterNFT) (*MsgRegisterNFTResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RegisterNFT not implemented") +func (m *MsgProposeRoleChangeResponse) Reset() { *m = MsgProposeRoleChangeResponse{} } +func (m *MsgProposeRoleChangeResponse) String() string { return proto.CompactTextString(m) } +func (*MsgProposeRoleChangeResponse) ProtoMessage() {} +func (*MsgProposeRoleChangeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{13} } -func (*UnimplementedMsgServer) GrantRole(ctx context.Context, req *MsgGrantRole) (*MsgGrantRoleResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GrantRole not implemented") +func (m *MsgProposeRoleChangeResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) } -func (*UnimplementedMsgServer) RevokeRole(ctx context.Context, req *MsgRevokeRole) (*MsgRevokeRoleResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RevokeRole not implemented") +func (m *MsgProposeRoleChangeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgProposeRoleChangeResponse.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 (*UnimplementedMsgServer) UnregisterNFT(ctx context.Context, req *MsgUnregisterNFT) (*MsgUnregisterNFTResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UnregisterNFT not implemented") +func (m *MsgProposeRoleChangeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgProposeRoleChangeResponse.Merge(m, src) } -func (*UnimplementedMsgServer) RegistryBulkUpdate(ctx context.Context, req *MsgRegistryBulkUpdate) (*MsgRegistryBulkUpdateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RegistryBulkUpdate not implemented") +func (m *MsgProposeRoleChangeResponse) XXX_Size() int { + return m.Size() } - -func RegisterMsgServer(s grpc1.Server, srv MsgServer) { - s.RegisterService(&_Msg_serviceDesc, srv) +func (m *MsgProposeRoleChangeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgProposeRoleChangeResponse.DiscardUnknown(m) } -func _Msg_RegisterNFT_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgRegisterNFT) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).RegisterNFT(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/provenance.registry.v1.Msg/RegisterNFT", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).RegisterNFT(ctx, req.(*MsgRegisterNFT)) +var xxx_messageInfo_MsgProposeRoleChangeResponse proto.InternalMessageInfo + +func (m *MsgProposeRoleChangeResponse) GetChangeId() string { + if m != nil { + return m.ChangeId } - return interceptor(ctx, in, info, handler) + return "" } -func _Msg_GrantRole_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgGrantRole) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).GrantRole(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/provenance.registry.v1.Msg/GrantRole", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).GrantRole(ctx, req.(*MsgGrantRole)) +func (m *MsgProposeRoleChangeResponse) GetApplied() bool { + if m != nil { + return m.Applied } - return interceptor(ctx, in, info, handler) + return false } -func _Msg_RevokeRole_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgRevokeRole) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).RevokeRole(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/provenance.registry.v1.Msg/RevokeRole", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).RevokeRole(ctx, req.(*MsgRevokeRole)) - } - return interceptor(ctx, in, info, handler) +// MsgApproveRoleChange records a single-signer approval for an open pending role change. +type MsgApproveRoleChange struct { + // signer is the approving party. Single-signer, so it can be delegated via authz. + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + // change_id is the identifier of the pending change to approve. + ChangeId string `protobuf:"bytes,2,opt,name=change_id,json=changeId,proto3" json:"change_id,omitempty"` } -func _Msg_UnregisterNFT_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgUnregisterNFT) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).UnregisterNFT(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/provenance.registry.v1.Msg/UnregisterNFT", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).UnregisterNFT(ctx, req.(*MsgUnregisterNFT)) - } - return interceptor(ctx, in, info, handler) +func (m *MsgApproveRoleChange) Reset() { *m = MsgApproveRoleChange{} } +func (m *MsgApproveRoleChange) String() string { return proto.CompactTextString(m) } +func (*MsgApproveRoleChange) ProtoMessage() {} +func (*MsgApproveRoleChange) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{14} } - -func _Msg_RegistryBulkUpdate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgRegistryBulkUpdate) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).RegistryBulkUpdate(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/provenance.registry.v1.Msg/RegistryBulkUpdate", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).RegistryBulkUpdate(ctx, req.(*MsgRegistryBulkUpdate)) +func (m *MsgApproveRoleChange) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgApproveRoleChange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgApproveRoleChange.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - return interceptor(ctx, in, info, handler) +} +func (m *MsgApproveRoleChange) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgApproveRoleChange.Merge(m, src) +} +func (m *MsgApproveRoleChange) XXX_Size() int { + return m.Size() +} +func (m *MsgApproveRoleChange) XXX_DiscardUnknown() { + xxx_messageInfo_MsgApproveRoleChange.DiscardUnknown(m) } -var Msg_serviceDesc = _Msg_serviceDesc -var _Msg_serviceDesc = grpc.ServiceDesc{ - ServiceName: "provenance.registry.v1.Msg", - HandlerType: (*MsgServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "RegisterNFT", - Handler: _Msg_RegisterNFT_Handler, - }, - { - MethodName: "GrantRole", - Handler: _Msg_GrantRole_Handler, - }, - { - MethodName: "RevokeRole", - Handler: _Msg_RevokeRole_Handler, - }, - { - MethodName: "UnregisterNFT", - Handler: _Msg_UnregisterNFT_Handler, - }, - { - MethodName: "RegistryBulkUpdate", - Handler: _Msg_RegistryBulkUpdate_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "provenance/registry/v1/tx.proto", +var xxx_messageInfo_MsgApproveRoleChange proto.InternalMessageInfo + +func (m *MsgApproveRoleChange) GetSigner() string { + if m != nil { + return m.Signer + } + return "" } -func (m *MsgRegisterNFT) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *MsgApproveRoleChange) GetChangeId() string { + if m != nil { + return m.ChangeId } - return dAtA[:n], nil + return "" } -func (m *MsgRegisterNFT) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// MsgApproveRoleChangeResponse defines the response for ApproveRoleChange. +type MsgApproveRoleChangeResponse struct { + // applied is true if this approval satisfied the policy and the change was applied. + Applied bool `protobuf:"varint,1,opt,name=applied,proto3" json:"applied,omitempty"` } -func (m *MsgRegisterNFT) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Roles) > 0 { - for iNdEx := len(m.Roles) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Roles[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - } - if m.Key != nil { - { - size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) +func (m *MsgApproveRoleChangeResponse) Reset() { *m = MsgApproveRoleChangeResponse{} } +func (m *MsgApproveRoleChangeResponse) String() string { return proto.CompactTextString(m) } +func (*MsgApproveRoleChangeResponse) ProtoMessage() {} +func (*MsgApproveRoleChangeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{15} +} +func (m *MsgApproveRoleChangeResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgApproveRoleChangeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgApproveRoleChangeResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } - i-- - dAtA[i] = 0x12 - } - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0xa + return b[:n], nil } - return len(dAtA) - i, nil } - -func (m *MsgRegisterNFTResponse) 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 *MsgApproveRoleChangeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgApproveRoleChangeResponse.Merge(m, src) } - -func (m *MsgRegisterNFTResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +func (m *MsgApproveRoleChangeResponse) XXX_Size() int { + return m.Size() } - -func (m *MsgRegisterNFTResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil +func (m *MsgApproveRoleChangeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgApproveRoleChangeResponse.DiscardUnknown(m) } -func (m *MsgGrantRole) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +var xxx_messageInfo_MsgApproveRoleChangeResponse proto.InternalMessageInfo + +func (m *MsgApproveRoleChangeResponse) GetApplied() bool { + if m != nil { + return m.Applied } - return dAtA[:n], nil + return false } -func (m *MsgGrantRole) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// MsgCancelRoleChange cancels an open pending role change. +// Only the original proposer may cancel. +type MsgCancelRoleChange struct { + // signer must be the original proposer of the pending change. + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + // change_id is the identifier of the pending change to cancel. + ChangeId string `protobuf:"bytes,2,opt,name=change_id,json=changeId,proto3" json:"change_id,omitempty"` } -func (m *MsgGrantRole) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Addresses) > 0 { - for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Addresses[iNdEx]) - copy(dAtA[i:], m.Addresses[iNdEx]) - i = encodeVarintTx(dAtA, i, uint64(len(m.Addresses[iNdEx]))) - i-- - dAtA[i] = 0x22 - } - } - if m.Role != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.Role)) - i-- - dAtA[i] = 0x18 - } - if m.Key != nil { - { - size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) +func (m *MsgCancelRoleChange) Reset() { *m = MsgCancelRoleChange{} } +func (m *MsgCancelRoleChange) String() string { return proto.CompactTextString(m) } +func (*MsgCancelRoleChange) ProtoMessage() {} +func (*MsgCancelRoleChange) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{16} +} +func (m *MsgCancelRoleChange) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCancelRoleChange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCancelRoleChange.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } - i-- - dAtA[i] = 0x12 - } - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0xa + return b[:n], nil } - return len(dAtA) - i, nil } - -func (m *MsgGrantRoleResponse) 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 *MsgCancelRoleChange) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCancelRoleChange.Merge(m, src) } - -func (m *MsgGrantRoleResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +func (m *MsgCancelRoleChange) XXX_Size() int { + return m.Size() +} +func (m *MsgCancelRoleChange) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCancelRoleChange.DiscardUnknown(m) } -func (m *MsgGrantRoleResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil +var xxx_messageInfo_MsgCancelRoleChange proto.InternalMessageInfo + +func (m *MsgCancelRoleChange) GetSigner() string { + if m != nil { + return m.Signer + } + return "" } -func (m *MsgRevokeRole) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *MsgCancelRoleChange) GetChangeId() string { + if m != nil { + return m.ChangeId } - return dAtA[:n], nil + return "" } -func (m *MsgRevokeRole) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// MsgCancelRoleChangeResponse defines the response for CancelRoleChange. +type MsgCancelRoleChangeResponse struct { } -func (m *MsgRevokeRole) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Addresses) > 0 { - for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Addresses[iNdEx]) - copy(dAtA[i:], m.Addresses[iNdEx]) - i = encodeVarintTx(dAtA, i, uint64(len(m.Addresses[iNdEx]))) - i-- - dAtA[i] = 0x22 +func (m *MsgCancelRoleChangeResponse) Reset() { *m = MsgCancelRoleChangeResponse{} } +func (m *MsgCancelRoleChangeResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCancelRoleChangeResponse) ProtoMessage() {} +func (*MsgCancelRoleChangeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{17} +} +func (m *MsgCancelRoleChangeResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCancelRoleChangeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCancelRoleChangeResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - if m.Role != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.Role)) - i-- - dAtA[i] = 0x18 - } - if m.Key != nil { - { - size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) +} +func (m *MsgCancelRoleChangeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCancelRoleChangeResponse.Merge(m, src) +} +func (m *MsgCancelRoleChangeResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCancelRoleChangeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCancelRoleChangeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCancelRoleChangeResponse proto.InternalMessageInfo + +// MsgAssociateRegistryClass associates or updates the registry class for an existing registry +// entry without modifying any roles. This is the upgrade path from legacy (no-class) registration +// to class-governed authorization. +// +// Authorization priority: +// 1. CONTROLLER: if the entry has a CONTROLLER role set, the signer must be one of those +// controllers. +// 2. Scope data owner: if the NFT is a Provenance Metadata Scope, the signer must be one of +// the scope's data-owner parties. +// 3. NFT owner: for all other NFTs with no controller set, the signer must own the NFT. +type MsgAssociateRegistryClass struct { + // signer is the address authorizing this association. + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + // key identifies the existing registry entry to update. + Key *RegistryKey `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + // registry_class_id is the ID of the registry class to associate. Pass an empty string to + // remove the current association and fall back to module-level authorization. + RegistryClassId string `protobuf:"bytes,3,opt,name=registry_class_id,json=registryClassId,proto3" json:"registryClassId,omitempty"` +} + +func (m *MsgAssociateRegistryClass) Reset() { *m = MsgAssociateRegistryClass{} } +func (m *MsgAssociateRegistryClass) String() string { return proto.CompactTextString(m) } +func (*MsgAssociateRegistryClass) ProtoMessage() {} +func (*MsgAssociateRegistryClass) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{18} +} +func (m *MsgAssociateRegistryClass) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAssociateRegistryClass) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAssociateRegistryClass.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } - i-- - dAtA[i] = 0x12 + return b[:n], nil } - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0xa +} +func (m *MsgAssociateRegistryClass) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAssociateRegistryClass.Merge(m, src) +} +func (m *MsgAssociateRegistryClass) XXX_Size() int { + return m.Size() +} +func (m *MsgAssociateRegistryClass) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAssociateRegistryClass.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAssociateRegistryClass proto.InternalMessageInfo + +func (m *MsgAssociateRegistryClass) GetSigner() string { + if m != nil { + return m.Signer } - return len(dAtA) - i, nil + return "" } -func (m *MsgRevokeRoleResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *MsgAssociateRegistryClass) GetKey() *RegistryKey { + if m != nil { + return m.Key } - return dAtA[:n], nil + return nil } -func (m *MsgRevokeRoleResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +func (m *MsgAssociateRegistryClass) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId + } + return "" } -func (m *MsgRevokeRoleResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil +// MsgAssociateRegistryClassResponse defines the response for AssociateRegistryClass. +type MsgAssociateRegistryClassResponse struct { } -func (m *MsgUnregisterNFT) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *MsgAssociateRegistryClassResponse) Reset() { *m = MsgAssociateRegistryClassResponse{} } +func (m *MsgAssociateRegistryClassResponse) String() string { return proto.CompactTextString(m) } +func (*MsgAssociateRegistryClassResponse) ProtoMessage() {} +func (*MsgAssociateRegistryClassResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{19} +} +func (m *MsgAssociateRegistryClassResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAssociateRegistryClassResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAssociateRegistryClassResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil } - return dAtA[:n], nil +} +func (m *MsgAssociateRegistryClassResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAssociateRegistryClassResponse.Merge(m, src) +} +func (m *MsgAssociateRegistryClassResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgAssociateRegistryClassResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAssociateRegistryClassResponse.DiscardUnknown(m) } -func (m *MsgUnregisterNFT) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +var xxx_messageInfo_MsgAssociateRegistryClassResponse proto.InternalMessageInfo + +// MsgCreateRegistryClass creates a new registry class defining asset class-level authorization +// rules for role updates within an NFT collection. +type MsgCreateRegistryClass struct { + // signer must match the maintainer address. + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + // registry_class_id is the unique identifier for the registry class. Must be unique across all + // registry classes. + RegistryClassId string `protobuf:"bytes,2,opt,name=registry_class_id,json=registryClassId,proto3" json:"registry_class_id,omitempty"` + // asset_class_id is the Scope Specification ID or NFT Class ID this registry class governs. + AssetClassId string `protobuf:"bytes,3,opt,name=asset_class_id,json=assetClassId,proto3" json:"asset_class_id,omitempty"` + // maintainer is the address authorized to manage this registry class. It is permanent and + // cannot be changed after creation. + Maintainer string `protobuf:"bytes,4,opt,name=maintainer,proto3" json:"maintainer,omitempty"` + // role_authorizations are the initial authorization rules for this asset class. + RoleAuthorizations []RoleAuthorization `protobuf:"bytes,5,rep,name=role_authorizations,json=roleAuthorizations,proto3" json:"role_authorizations"` } -func (m *MsgUnregisterNFT) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Key != nil { - { - size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) +func (m *MsgCreateRegistryClass) Reset() { *m = MsgCreateRegistryClass{} } +func (m *MsgCreateRegistryClass) String() string { return proto.CompactTextString(m) } +func (*MsgCreateRegistryClass) ProtoMessage() {} +func (*MsgCreateRegistryClass) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{20} +} +func (m *MsgCreateRegistryClass) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateRegistryClass) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateRegistryClass.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } - i-- - dAtA[i] = 0x12 + return b[:n], nil } - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0xa +} +func (m *MsgCreateRegistryClass) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateRegistryClass.Merge(m, src) +} +func (m *MsgCreateRegistryClass) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateRegistryClass) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateRegistryClass.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateRegistryClass proto.InternalMessageInfo + +func (m *MsgCreateRegistryClass) GetSigner() string { + if m != nil { + return m.Signer } - return len(dAtA) - i, nil + return "" } -func (m *MsgUnregisterNFTResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *MsgCreateRegistryClass) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId } - return dAtA[:n], nil + return "" } -func (m *MsgUnregisterNFTResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +func (m *MsgCreateRegistryClass) GetAssetClassId() string { + if m != nil { + return m.AssetClassId + } + return "" } -func (m *MsgUnregisterNFTResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil +func (m *MsgCreateRegistryClass) GetMaintainer() string { + if m != nil { + return m.Maintainer + } + return "" } -func (m *MsgRegistryBulkUpdate) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func (m *MsgCreateRegistryClass) GetRoleAuthorizations() []RoleAuthorization { + if m != nil { + return m.RoleAuthorizations } - return dAtA[:n], nil + return nil } -func (m *MsgRegistryBulkUpdate) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +// MsgCreateRegistryClassResponse defines the response for CreateRegistryClass. +type MsgCreateRegistryClassResponse struct { } -func (m *MsgRegistryBulkUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Entries) > 0 { - for iNdEx := len(m.Entries) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Entries[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 +func (m *MsgCreateRegistryClassResponse) Reset() { *m = MsgCreateRegistryClassResponse{} } +func (m *MsgCreateRegistryClassResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateRegistryClassResponse) ProtoMessage() {} +func (*MsgCreateRegistryClassResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{21} +} +func (m *MsgCreateRegistryClassResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateRegistryClassResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateRegistryClassResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil } - -func (m *MsgRegistryBulkUpdateResponse) 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 *MsgCreateRegistryClassResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateRegistryClassResponse.Merge(m, src) } - -func (m *MsgRegistryBulkUpdateResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) +func (m *MsgCreateRegistryClassResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateRegistryClassResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateRegistryClassResponse.DiscardUnknown(m) } -func (m *MsgRegistryBulkUpdateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil +var xxx_messageInfo_MsgCreateRegistryClassResponse proto.InternalMessageInfo + +// MsgUpdateRegistryClassRoleAuthorization replaces the authorization rules for an existing +// registry class. The new rules completely replace the existing rules (not a merge). +type MsgUpdateRegistryClassRoleAuthorization struct { + // signer must be the current maintainer address. + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + // registry_class_id identifies the registry class to update. + RegistryClassId string `protobuf:"bytes,2,opt,name=registry_class_id,json=registryClassId,proto3" json:"registry_class_id,omitempty"` + // role_authorizations are the updated authorization rules (replaces existing rules). + RoleAuthorizations []RoleAuthorization `protobuf:"bytes,3,rep,name=role_authorizations,json=roleAuthorizations,proto3" json:"role_authorizations"` } -func encodeVarintTx(dAtA []byte, offset int, v uint64) int { - offset -= sovTx(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base +func (m *MsgUpdateRegistryClassRoleAuthorization) Reset() { + *m = MsgUpdateRegistryClassRoleAuthorization{} } -func (m *MsgRegisterNFT) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.Key != nil { - l = m.Key.Size() - n += 1 + l + sovTx(uint64(l)) - } - if len(m.Roles) > 0 { - for _, e := range m.Roles { - l = e.Size() - n += 1 + l + sovTx(uint64(l)) +func (m *MsgUpdateRegistryClassRoleAuthorization) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateRegistryClassRoleAuthorization) ProtoMessage() {} +func (*MsgUpdateRegistryClassRoleAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{22} +} +func (m *MsgUpdateRegistryClassRoleAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateRegistryClassRoleAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateRegistryClassRoleAuthorization.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - return n +} +func (m *MsgUpdateRegistryClassRoleAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateRegistryClassRoleAuthorization.Merge(m, src) +} +func (m *MsgUpdateRegistryClassRoleAuthorization) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateRegistryClassRoleAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateRegistryClassRoleAuthorization.DiscardUnknown(m) } -func (m *MsgRegisterNFTResponse) Size() (n int) { - if m == nil { - return 0 +var xxx_messageInfo_MsgUpdateRegistryClassRoleAuthorization proto.InternalMessageInfo + +func (m *MsgUpdateRegistryClassRoleAuthorization) GetSigner() string { + if m != nil { + return m.Signer } - var l int - _ = l - return n + return "" } -func (m *MsgGrantRole) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.Key != nil { - l = m.Key.Size() - n += 1 + l + sovTx(uint64(l)) +func (m *MsgUpdateRegistryClassRoleAuthorization) GetRegistryClassId() string { + if m != nil { + return m.RegistryClassId } - if m.Role != 0 { - n += 1 + sovTx(uint64(m.Role)) + return "" +} + +func (m *MsgUpdateRegistryClassRoleAuthorization) GetRoleAuthorizations() []RoleAuthorization { + if m != nil { + return m.RoleAuthorizations } - if len(m.Addresses) > 0 { - for _, s := range m.Addresses { - l = len(s) - n += 1 + l + sovTx(uint64(l)) + return nil +} + +// MsgUpdateRegistryClassRoleAuthorizationResponse defines the response for +// UpdateRegistryClassRoleAuthorization. +type MsgUpdateRegistryClassRoleAuthorizationResponse struct { +} + +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) Reset() { + *m = MsgUpdateRegistryClassRoleAuthorizationResponse{} +} +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) String() string { + return proto.CompactTextString(m) +} +func (*MsgUpdateRegistryClassRoleAuthorizationResponse) ProtoMessage() {} +func (*MsgUpdateRegistryClassRoleAuthorizationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{23} +} +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateRegistryClassRoleAuthorizationResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - return n +} +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateRegistryClassRoleAuthorizationResponse.Merge(m, src) +} +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateRegistryClassRoleAuthorizationResponse.DiscardUnknown(m) } -func (m *MsgGrantRoleResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n +var xxx_messageInfo_MsgUpdateRegistryClassRoleAuthorizationResponse proto.InternalMessageInfo + +// MsgUpdateParams is a request to update the registry module's params. +type MsgUpdateParams struct { + // authority should be the governance module account address. + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // params are the new registry module params to set. + Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` } -func (m *MsgRevokeRole) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.Key != nil { - l = m.Key.Size() - n += 1 + l + sovTx(uint64(l)) - } - if m.Role != 0 { - n += 1 + sovTx(uint64(m.Role)) - } - if len(m.Addresses) > 0 { - for _, s := range m.Addresses { - l = len(s) - n += 1 + l + sovTx(uint64(l)) +func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } +func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParams) ProtoMessage() {} +func (*MsgUpdateParams) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{24} +} +func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - return n +} +func (m *MsgUpdateParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParams.Merge(m, src) +} +func (m *MsgUpdateParams) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParams) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) } -func (m *MsgRevokeRoleResponse) Size() (n int) { - if m == nil { - return 0 +var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo + +func (m *MsgUpdateParams) GetAuthority() string { + if m != nil { + return m.Authority } - var l int - _ = l - return n + return "" } -func (m *MsgUnregisterNFT) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.Key != nil { - l = m.Key.Size() - n += 1 + l + sovTx(uint64(l)) +func (m *MsgUpdateParams) GetParams() Params { + if m != nil { + return m.Params } - return n + return Params{} } -func (m *MsgUnregisterNFTResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n +// MsgUpdateParamsResponse defines the response for UpdateParams. +type MsgUpdateParamsResponse struct { } -func (m *MsgRegistryBulkUpdate) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if len(m.Entries) > 0 { - for _, e := range m.Entries { - l = e.Size() - n += 1 + l + sovTx(uint64(l)) +func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } +func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParamsResponse) ProtoMessage() {} +func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_afab3f18b6d8353c, []int{25} +} +func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err } + return b[:n], nil } - return n +} +func (m *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) +} +func (m *MsgUpdateParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) } -func (m *MsgRegistryBulkUpdateResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n +var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgRegisterNFT)(nil), "provenance.registry.v1.MsgRegisterNFT") + proto.RegisterType((*MsgRegisterNFTResponse)(nil), "provenance.registry.v1.MsgRegisterNFTResponse") + proto.RegisterType((*MsgGrantRole)(nil), "provenance.registry.v1.MsgGrantRole") + proto.RegisterType((*MsgGrantRoleResponse)(nil), "provenance.registry.v1.MsgGrantRoleResponse") + proto.RegisterType((*MsgRevokeRole)(nil), "provenance.registry.v1.MsgRevokeRole") + proto.RegisterType((*MsgRevokeRoleResponse)(nil), "provenance.registry.v1.MsgRevokeRoleResponse") + proto.RegisterType((*MsgUnregisterNFT)(nil), "provenance.registry.v1.MsgUnregisterNFT") + proto.RegisterType((*MsgUnregisterNFTResponse)(nil), "provenance.registry.v1.MsgUnregisterNFTResponse") + proto.RegisterType((*MsgRegistryBulkUpdate)(nil), "provenance.registry.v1.MsgRegistryBulkUpdate") + proto.RegisterType((*MsgRegistryBulkUpdateResponse)(nil), "provenance.registry.v1.MsgRegistryBulkUpdateResponse") + proto.RegisterType((*MsgSetRoles)(nil), "provenance.registry.v1.MsgSetRoles") + proto.RegisterType((*MsgSetRolesResponse)(nil), "provenance.registry.v1.MsgSetRolesResponse") + proto.RegisterType((*MsgProposeRoleChange)(nil), "provenance.registry.v1.MsgProposeRoleChange") + proto.RegisterType((*MsgProposeRoleChangeResponse)(nil), "provenance.registry.v1.MsgProposeRoleChangeResponse") + proto.RegisterType((*MsgApproveRoleChange)(nil), "provenance.registry.v1.MsgApproveRoleChange") + proto.RegisterType((*MsgApproveRoleChangeResponse)(nil), "provenance.registry.v1.MsgApproveRoleChangeResponse") + proto.RegisterType((*MsgCancelRoleChange)(nil), "provenance.registry.v1.MsgCancelRoleChange") + proto.RegisterType((*MsgCancelRoleChangeResponse)(nil), "provenance.registry.v1.MsgCancelRoleChangeResponse") + proto.RegisterType((*MsgAssociateRegistryClass)(nil), "provenance.registry.v1.MsgAssociateRegistryClass") + proto.RegisterType((*MsgAssociateRegistryClassResponse)(nil), "provenance.registry.v1.MsgAssociateRegistryClassResponse") + proto.RegisterType((*MsgCreateRegistryClass)(nil), "provenance.registry.v1.MsgCreateRegistryClass") + proto.RegisterType((*MsgCreateRegistryClassResponse)(nil), "provenance.registry.v1.MsgCreateRegistryClassResponse") + proto.RegisterType((*MsgUpdateRegistryClassRoleAuthorization)(nil), "provenance.registry.v1.MsgUpdateRegistryClassRoleAuthorization") + proto.RegisterType((*MsgUpdateRegistryClassRoleAuthorizationResponse)(nil), "provenance.registry.v1.MsgUpdateRegistryClassRoleAuthorizationResponse") + proto.RegisterType((*MsgUpdateParams)(nil), "provenance.registry.v1.MsgUpdateParams") + proto.RegisterType((*MsgUpdateParamsResponse)(nil), "provenance.registry.v1.MsgUpdateParamsResponse") } -func sovTx(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 +func init() { proto.RegisterFile("provenance/registry/v1/tx.proto", fileDescriptor_afab3f18b6d8353c) } + +var fileDescriptor_afab3f18b6d8353c = []byte{ + // 1132 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0x4f, 0x6f, 0xe3, 0xc4, + 0x1b, 0xee, 0x34, 0x6d, 0xb7, 0x7d, 0xd3, 0xed, 0xee, 0xba, 0xdd, 0xd6, 0xf1, 0xfe, 0x9a, 0xe6, + 0x97, 0xb6, 0x6c, 0x28, 0xdb, 0x64, 0xdb, 0xfd, 0xa3, 0xb2, 0x42, 0xa0, 0xb6, 0x5a, 0x56, 0xd5, + 0x2a, 0xa8, 0xf2, 0xd2, 0x0b, 0x42, 0x0a, 0x6e, 0x32, 0x72, 0xad, 0x24, 0xb6, 0x99, 0x71, 0xcb, + 0x66, 0x25, 0x24, 0xc4, 0x01, 0x71, 0xe0, 0x00, 0x27, 0x4e, 0x7c, 0x87, 0x1e, 0xf8, 0x0a, 0x48, + 0x7b, 0xac, 0x38, 0x81, 0x84, 0x56, 0xa8, 0x3d, 0xac, 0xc4, 0x07, 0x80, 0x2b, 0xf2, 0xd8, 0x9e, + 0xd8, 0x8e, 0xed, 0x38, 0x94, 0x2d, 0x12, 0xdc, 0x62, 0xcf, 0xf3, 0xce, 0xfb, 0x3c, 0xcf, 0xcc, + 0x3b, 0xf3, 0xc6, 0xb0, 0x60, 0x12, 0xe3, 0x08, 0xeb, 0x8a, 0x5e, 0xc7, 0x15, 0x82, 0x55, 0x8d, + 0x5a, 0xa4, 0x53, 0x39, 0x5a, 0xab, 0x58, 0x4f, 0xcb, 0x26, 0x31, 0x2c, 0x43, 0x98, 0xed, 0x02, + 0xca, 0x1e, 0xa0, 0x7c, 0xb4, 0x26, 0xcd, 0xa8, 0x86, 0x6a, 0x30, 0x48, 0xc5, 0xfe, 0xe5, 0xa0, + 0xa5, 0x5c, 0xdd, 0xa0, 0x6d, 0x83, 0xd6, 0x9c, 0x01, 0xe7, 0xc1, 0x1d, 0x9a, 0x73, 0x9e, 0x2a, + 0x6d, 0xaa, 0xda, 0x09, 0xda, 0x54, 0x75, 0x07, 0x96, 0x63, 0x28, 0xf0, 0x6c, 0x0e, 0x6c, 0x25, + 0x06, 0xa6, 0x1c, 0x5a, 0x07, 0x06, 0xd1, 0x9e, 0x29, 0x96, 0x66, 0xe8, 0x2e, 0x76, 0x31, 0x06, + 0x6b, 0x2a, 0x44, 0x69, 0xbb, 0x84, 0x8a, 0xdf, 0x0c, 0xc3, 0x54, 0x95, 0xaa, 0x32, 0x1b, 0xc7, + 0xe4, 0xbd, 0x77, 0xdf, 0x17, 0x6e, 0xc3, 0x18, 0xd5, 0x54, 0x1d, 0x13, 0x11, 0x15, 0x50, 0x69, + 0x62, 0x4b, 0xfc, 0xf1, 0xfb, 0xd5, 0x19, 0x57, 0xc5, 0x66, 0xa3, 0x41, 0x30, 0xa5, 0x4f, 0x2c, + 0xa2, 0xe9, 0xaa, 0xec, 0xe2, 0x84, 0x7b, 0x90, 0x69, 0xe2, 0x8e, 0x38, 0x5c, 0x40, 0xa5, 0xec, + 0xfa, 0x62, 0x39, 0xda, 0xac, 0xb2, 0xec, 0xfe, 0x7e, 0x8c, 0x3b, 0xb2, 0x8d, 0x17, 0xde, 0x86, + 0x51, 0x62, 0xb4, 0x30, 0x15, 0x33, 0x85, 0x4c, 0x29, 0xbb, 0x5e, 0x8c, 0x0d, 0xb4, 0x41, 0x0f, + 0x75, 0x8b, 0x74, 0xb6, 0x46, 0x9e, 0xbf, 0x58, 0x18, 0x92, 0x9d, 0x30, 0x61, 0x07, 0xae, 0x79, + 0xb0, 0x5a, 0xbd, 0xa5, 0x50, 0x5a, 0xd3, 0x1a, 0xe2, 0x08, 0xe3, 0x3c, 0xff, 0xdb, 0x8b, 0x85, + 0x9c, 0x37, 0xb8, 0x6d, 0x8f, 0xed, 0x34, 0x6e, 0x19, 0x6d, 0xcd, 0xc2, 0x6d, 0xd3, 0xea, 0xc8, + 0x57, 0x42, 0x43, 0x0f, 0xb2, 0x9f, 0xbf, 0x3c, 0x5e, 0x71, 0xe5, 0x14, 0x45, 0x98, 0x0d, 0x5a, + 0x22, 0x63, 0x6a, 0x1a, 0x3a, 0xc5, 0xc5, 0xdf, 0x11, 0x4c, 0x56, 0xa9, 0xfa, 0x88, 0x28, 0xba, + 0x65, 0xb3, 0xba, 0x38, 0xaf, 0x36, 0x60, 0xc4, 0x16, 0x2d, 0x66, 0x0a, 0xa8, 0x34, 0xb5, 0xbe, + 0xd4, 0x2f, 0xce, 0x26, 0x27, 0xb3, 0x08, 0xe1, 0x3e, 0x4c, 0x28, 0x0e, 0x13, 0x4c, 0xc5, 0x91, + 0x42, 0x26, 0x91, 0x65, 0x17, 0x1a, 0xb4, 0x64, 0x16, 0x66, 0xfc, 0xba, 0xb9, 0x21, 0x7f, 0x20, + 0xb8, 0xcc, 0xbc, 0x3a, 0x32, 0x9a, 0xf8, 0x3f, 0xe5, 0xc8, 0x1c, 0x5c, 0x0f, 0x08, 0xe7, 0x96, + 0x7c, 0x89, 0xe0, 0x6a, 0x95, 0xaa, 0x7b, 0x3a, 0xf9, 0x07, 0x6a, 0x2a, 0xc8, 0x51, 0x02, 0x31, + 0xcc, 0x84, 0xd3, 0xfc, 0x0e, 0xb9, 0x02, 0x9c, 0x09, 0xb6, 0x0e, 0x5b, 0xcd, 0x3d, 0xb3, 0xa1, + 0x58, 0x7f, 0x65, 0x05, 0x1f, 0xc2, 0x25, 0xac, 0x5b, 0x44, 0xc3, 0x54, 0x1c, 0x66, 0xa5, 0xbc, + 0xdc, 0x8f, 0xaf, 0xbf, 0x9a, 0xbd, 0xd8, 0x20, 0xf7, 0x05, 0x98, 0x8f, 0xa4, 0xc7, 0x05, 0x9c, + 0x20, 0xc8, 0x56, 0xa9, 0xfa, 0x04, 0xb3, 0x1d, 0x49, 0x2f, 0x6e, 0xe3, 0x3d, 0x86, 0x49, 0x7b, + 0x1b, 0xd5, 0x0e, 0x19, 0x9f, 0x54, 0xa7, 0x97, 0x43, 0xdd, 0xd5, 0x9b, 0x25, 0xfc, 0x4d, 0x48, + 0xf3, 0x75, 0x98, 0xf6, 0x29, 0xe2, 0x4a, 0x7f, 0x46, 0xac, 0xfa, 0x76, 0x89, 0x61, 0x1a, 0x94, + 0x6d, 0xb6, 0xed, 0x03, 0x45, 0x57, 0xf1, 0xbf, 0x41, 0xf2, 0x1e, 0xfc, 0x2f, 0x4a, 0x9a, 0xa7, + 0x5d, 0xb8, 0x01, 0x13, 0x75, 0xf6, 0xc6, 0x3e, 0xdb, 0x99, 0x4a, 0x79, 0xdc, 0x79, 0xb1, 0xd3, + 0x10, 0x44, 0xb8, 0xa4, 0x98, 0x66, 0x4b, 0xc3, 0x0d, 0xa6, 0x68, 0x5c, 0xf6, 0x1e, 0x8b, 0x84, + 0x39, 0xb6, 0x69, 0x32, 0x82, 0xe7, 0x72, 0x2c, 0x40, 0x60, 0x38, 0x48, 0x20, 0x28, 0x65, 0x83, + 0x49, 0xe9, 0xc9, 0xc9, 0xa5, 0xf8, 0xd8, 0xa2, 0x20, 0xdb, 0x8f, 0xd9, 0xba, 0x6f, 0xdb, 0x3e, + 0xb6, 0x2e, 0x88, 0xec, 0x3c, 0xdc, 0x88, 0x48, 0xc9, 0xb7, 0xdc, 0x2f, 0x08, 0x72, 0xb6, 0x18, + 0x4a, 0x8d, 0xba, 0xc6, 0xaa, 0xce, 0x77, 0x5f, 0x5e, 0xdc, 0xbe, 0x8b, 0xbc, 0xe1, 0x33, 0xe7, + 0xbf, 0xe1, 0x17, 0xe1, 0xff, 0xb1, 0xea, 0xb8, 0x07, 0x3f, 0x0c, 0xb3, 0x3e, 0x60, 0x9b, 0xe0, + 0xbf, 0xc1, 0x80, 0x95, 0x28, 0x25, 0xce, 0x0a, 0x85, 0xa9, 0x0a, 0x4b, 0x30, 0xa5, 0x50, 0x8a, + 0xad, 0x90, 0x64, 0x79, 0x92, 0xbd, 0xf5, 0x50, 0x1b, 0x00, 0x6d, 0x45, 0xd3, 0x2d, 0x45, 0xb3, + 0x79, 0x8c, 0xf4, 0xe1, 0xe1, 0xc3, 0x0a, 0x1f, 0xc1, 0x34, 0xab, 0xe6, 0x40, 0xd3, 0x48, 0xc5, + 0x51, 0x56, 0xd4, 0xaf, 0x27, 0x15, 0xf5, 0xa6, 0x3f, 0xc2, 0xad, 0x6d, 0x81, 0x84, 0x07, 0x42, + 0x25, 0x5e, 0x80, 0x7c, 0xb4, 0x8d, 0xfe, 0xb6, 0xea, 0xa6, 0x7d, 0x51, 0xb9, 0x07, 0xbc, 0x1f, + 0x12, 0x9e, 0xfb, 0x15, 0x5b, 0x1f, 0x63, 0x4d, 0xe6, 0x15, 0x59, 0xb3, 0x06, 0x95, 0x94, 0xba, + 0xb9, 0x57, 0xdf, 0x22, 0xb8, 0xc2, 0x63, 0x76, 0x59, 0x2b, 0xcf, 0x1a, 0x1a, 0x07, 0x6c, 0x75, + 0xfa, 0xda, 0xd2, 0x85, 0x0a, 0x6f, 0xc1, 0x98, 0xf3, 0x67, 0xc0, 0x2d, 0xcc, 0x7c, 0x9c, 0x40, + 0x27, 0x8f, 0xab, 0xca, 0x8d, 0x79, 0x30, 0x65, 0x2b, 0xe9, 0xce, 0x56, 0xcc, 0xc1, 0x5c, 0x88, + 0x98, 0x47, 0x7a, 0xfd, 0xab, 0x49, 0xc8, 0x54, 0xa9, 0x2a, 0x60, 0xc8, 0xfa, 0xff, 0x69, 0xbc, + 0x16, 0x97, 0x2f, 0xd8, 0x7e, 0x4b, 0xe5, 0x74, 0x38, 0x7e, 0xd2, 0xd6, 0x60, 0xa2, 0xdb, 0xa2, + 0x2f, 0x25, 0x04, 0x73, 0x94, 0x74, 0x2b, 0x0d, 0x8a, 0x27, 0xd8, 0x07, 0xf0, 0xb5, 0xbc, 0xcb, + 0x89, 0xf4, 0x3c, 0x98, 0xb4, 0x9a, 0x0a, 0xc6, 0x73, 0x34, 0xe1, 0x72, 0xb0, 0x87, 0x2c, 0x25, + 0xc4, 0x07, 0x90, 0xd2, 0xed, 0xb4, 0x48, 0x9e, 0xec, 0x19, 0x08, 0x11, 0x9d, 0xe0, 0x6a, 0x5f, + 0xdf, 0xfd, 0x70, 0xe9, 0xde, 0x40, 0x70, 0x9e, 0xfb, 0x43, 0x18, 0xe7, 0x4d, 0xdc, 0x62, 0xc2, + 0x14, 0x1e, 0x48, 0x7a, 0x23, 0x05, 0x88, 0xcf, 0xfe, 0x09, 0x5c, 0xeb, 0x6d, 0x9c, 0x92, 0x56, + 0xbb, 0x07, 0x2d, 0xdd, 0x1d, 0x04, 0xed, 0x4f, 0xdc, 0xdb, 0x7f, 0x24, 0x25, 0xee, 0x41, 0x27, + 0x26, 0x8e, 0xef, 0x33, 0x3e, 0x85, 0xe9, 0xa8, 0x3b, 0x2b, 0xa9, 0x88, 0x22, 0xf0, 0xd2, 0xfd, + 0xc1, 0xf0, 0x3c, 0xfd, 0x31, 0x82, 0xa5, 0x54, 0x27, 0xf9, 0x3b, 0x49, 0xbb, 0x34, 0xc5, 0x04, + 0xd2, 0xa3, 0x73, 0x4e, 0xc0, 0x29, 0x5b, 0x70, 0xb5, 0xa7, 0xf9, 0x4a, 0xda, 0x64, 0x61, 0xb0, + 0x74, 0x67, 0x00, 0x30, 0xcf, 0xfa, 0x05, 0x82, 0xd9, 0x98, 0x06, 0x6b, 0x2d, 0x69, 0xe1, 0x23, + 0x43, 0xa4, 0x37, 0x07, 0x0e, 0xe1, 0x44, 0x0e, 0x60, 0x32, 0x70, 0x9d, 0xdc, 0xec, 0xeb, 0xab, + 0x03, 0x94, 0x2a, 0x29, 0x81, 0x5e, 0x26, 0x69, 0xf4, 0xb3, 0x97, 0xc7, 0x2b, 0x68, 0xab, 0xf9, + 0xfc, 0x34, 0x8f, 0x4e, 0x4e, 0xf3, 0xe8, 0xd7, 0xd3, 0x3c, 0xfa, 0xfa, 0x2c, 0x3f, 0x74, 0x72, + 0x96, 0x1f, 0xfa, 0xe9, 0x2c, 0x3f, 0x04, 0x39, 0xcd, 0x88, 0x99, 0x73, 0x17, 0x7d, 0x70, 0x57, + 0xd5, 0xac, 0x83, 0xc3, 0xfd, 0x72, 0xdd, 0x68, 0x57, 0xba, 0xa0, 0x55, 0xcd, 0xf0, 0x3d, 0x55, + 0x9e, 0x76, 0xbf, 0x75, 0x59, 0x1d, 0x13, 0xd3, 0xfd, 0x31, 0xf6, 0xa1, 0xeb, 0xce, 0x9f, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x75, 0x7b, 0xef, 0x18, 0xe5, 0x13, 0x00, 0x00, } -func sozTx(x uint64) (n int) { - return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) + +// 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 { + // RegisterNFT registers a new NFT in the registry. + // This creates a new registry entry with the specified roles and addresses. + RegisterNFT(ctx context.Context, in *MsgRegisterNFT, opts ...grpc.CallOption) (*MsgRegisterNFTResponse, error) + // GrantRole grants a role to one or more addresses. + // This adds the specified addresses to the role for the given registry key. + // The single signer must satisfy the role's authorization policy directly; multi-party role + // changes are made through ProposeRoleChange / ApproveRoleChange. + GrantRole(ctx context.Context, in *MsgGrantRole, opts ...grpc.CallOption) (*MsgGrantRoleResponse, error) + // RevokeRole revokes a role from one or more addresses. + // This removes the specified addresses from the role for the given registry key. + // The single signer must satisfy the role's authorization policy directly; multi-party role + // changes are made through ProposeRoleChange / ApproveRoleChange. + RevokeRole(ctx context.Context, in *MsgRevokeRole, opts ...grpc.CallOption) (*MsgRevokeRoleResponse, error) + // UnregisterNFT unregisters an NFT from the registry. + // This removes the entire registry entry for the specified key. + UnregisterNFT(ctx context.Context, in *MsgUnregisterNFT, opts ...grpc.CallOption) (*MsgUnregisterNFTResponse, error) + // RegistryBulkUpdate registers, or updates, multiple NFTs in the registry. + // This creates multiple registry entries, or updates if one exists. + // Each registry in this will cost one MsgRegisterNFT. + RegistryBulkUpdate(ctx context.Context, in *MsgRegistryBulkUpdate, opts ...grpc.CallOption) (*MsgRegistryBulkUpdateResponse, error) + // SetRoles atomically sets the desired state for one or more roles on a registry entry. + // The single signer must satisfy each affected role's authorization policy directly; multi-party + // role changes are made through ProposeRoleChange / ApproveRoleChange. + SetRoles(ctx context.Context, in *MsgSetRoles, opts ...grpc.CallOption) (*MsgSetRolesResponse, error) + // ProposeRoleChange opens a pending role change that accumulates single-signer approvals. + // The change auto-applies once the role's authorization policy is satisfied. + ProposeRoleChange(ctx context.Context, in *MsgProposeRoleChange, opts ...grpc.CallOption) (*MsgProposeRoleChangeResponse, error) + // ApproveRoleChange records a single-signer approval for an open pending role change. + // When the accumulated approvals satisfy the role's policy, the change is applied automatically. + ApproveRoleChange(ctx context.Context, in *MsgApproveRoleChange, opts ...grpc.CallOption) (*MsgApproveRoleChangeResponse, error) + // CreateRegistryClass creates a new registry class that defines asset class-level authorization + // rules for role updates. The signer must match the maintainer address. + CreateRegistryClass(ctx context.Context, in *MsgCreateRegistryClass, opts ...grpc.CallOption) (*MsgCreateRegistryClassResponse, error) + // UpdateRegistryClassRoleAuthorization replaces the authorization rules for an existing registry + // class. Only the current maintainer may update the rules. + UpdateRegistryClassRoleAuthorization(ctx context.Context, in *MsgUpdateRegistryClassRoleAuthorization, opts ...grpc.CallOption) (*MsgUpdateRegistryClassRoleAuthorizationResponse, error) + // CancelRoleChange cancels an open pending role change. + // Only the original proposer may cancel. + CancelRoleChange(ctx context.Context, in *MsgCancelRoleChange, opts ...grpc.CallOption) (*MsgCancelRoleChangeResponse, error) + // AssociateRegistryClass associates or updates the registry class for an existing registry entry + // without modifying any roles. The signer must be the CONTROLLER if one is set, or the scope + // data owner if the NFT is a Provenance Metadata Scope, or the NFT owner otherwise. + AssociateRegistryClass(ctx context.Context, in *MsgAssociateRegistryClass, opts ...grpc.CallOption) (*MsgAssociateRegistryClassResponse, error) + // UpdateParams is a governance proposal endpoint for updating the registry module's params, + // including the default role authorization policies. The authority must be the governance module + // account address. + UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) RegisterNFT(ctx context.Context, in *MsgRegisterNFT, opts ...grpc.CallOption) (*MsgRegisterNFTResponse, error) { + out := new(MsgRegisterNFTResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/RegisterNFT", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) GrantRole(ctx context.Context, in *MsgGrantRole, opts ...grpc.CallOption) (*MsgGrantRoleResponse, error) { + out := new(MsgGrantRoleResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/GrantRole", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) RevokeRole(ctx context.Context, in *MsgRevokeRole, opts ...grpc.CallOption) (*MsgRevokeRoleResponse, error) { + out := new(MsgRevokeRoleResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/RevokeRole", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UnregisterNFT(ctx context.Context, in *MsgUnregisterNFT, opts ...grpc.CallOption) (*MsgUnregisterNFTResponse, error) { + out := new(MsgUnregisterNFTResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/UnregisterNFT", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) RegistryBulkUpdate(ctx context.Context, in *MsgRegistryBulkUpdate, opts ...grpc.CallOption) (*MsgRegistryBulkUpdateResponse, error) { + out := new(MsgRegistryBulkUpdateResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/RegistryBulkUpdate", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) SetRoles(ctx context.Context, in *MsgSetRoles, opts ...grpc.CallOption) (*MsgSetRolesResponse, error) { + out := new(MsgSetRolesResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/SetRoles", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) ProposeRoleChange(ctx context.Context, in *MsgProposeRoleChange, opts ...grpc.CallOption) (*MsgProposeRoleChangeResponse, error) { + out := new(MsgProposeRoleChangeResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/ProposeRoleChange", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) ApproveRoleChange(ctx context.Context, in *MsgApproveRoleChange, opts ...grpc.CallOption) (*MsgApproveRoleChangeResponse, error) { + out := new(MsgApproveRoleChangeResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/ApproveRoleChange", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) CreateRegistryClass(ctx context.Context, in *MsgCreateRegistryClass, opts ...grpc.CallOption) (*MsgCreateRegistryClassResponse, error) { + out := new(MsgCreateRegistryClassResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/CreateRegistryClass", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateRegistryClassRoleAuthorization(ctx context.Context, in *MsgUpdateRegistryClassRoleAuthorization, opts ...grpc.CallOption) (*MsgUpdateRegistryClassRoleAuthorizationResponse, error) { + out := new(MsgUpdateRegistryClassRoleAuthorizationResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/UpdateRegistryClassRoleAuthorization", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) CancelRoleChange(ctx context.Context, in *MsgCancelRoleChange, opts ...grpc.CallOption) (*MsgCancelRoleChangeResponse, error) { + out := new(MsgCancelRoleChangeResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/CancelRoleChange", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) AssociateRegistryClass(ctx context.Context, in *MsgAssociateRegistryClass, opts ...grpc.CallOption) (*MsgAssociateRegistryClassResponse, error) { + out := new(MsgAssociateRegistryClassResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/AssociateRegistryClass", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/provenance.registry.v1.Msg/UpdateParams", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // RegisterNFT registers a new NFT in the registry. + // This creates a new registry entry with the specified roles and addresses. + RegisterNFT(context.Context, *MsgRegisterNFT) (*MsgRegisterNFTResponse, error) + // GrantRole grants a role to one or more addresses. + // This adds the specified addresses to the role for the given registry key. + // The single signer must satisfy the role's authorization policy directly; multi-party role + // changes are made through ProposeRoleChange / ApproveRoleChange. + GrantRole(context.Context, *MsgGrantRole) (*MsgGrantRoleResponse, error) + // RevokeRole revokes a role from one or more addresses. + // This removes the specified addresses from the role for the given registry key. + // The single signer must satisfy the role's authorization policy directly; multi-party role + // changes are made through ProposeRoleChange / ApproveRoleChange. + RevokeRole(context.Context, *MsgRevokeRole) (*MsgRevokeRoleResponse, error) + // UnregisterNFT unregisters an NFT from the registry. + // This removes the entire registry entry for the specified key. + UnregisterNFT(context.Context, *MsgUnregisterNFT) (*MsgUnregisterNFTResponse, error) + // RegistryBulkUpdate registers, or updates, multiple NFTs in the registry. + // This creates multiple registry entries, or updates if one exists. + // Each registry in this will cost one MsgRegisterNFT. + RegistryBulkUpdate(context.Context, *MsgRegistryBulkUpdate) (*MsgRegistryBulkUpdateResponse, error) + // SetRoles atomically sets the desired state for one or more roles on a registry entry. + // The single signer must satisfy each affected role's authorization policy directly; multi-party + // role changes are made through ProposeRoleChange / ApproveRoleChange. + SetRoles(context.Context, *MsgSetRoles) (*MsgSetRolesResponse, error) + // ProposeRoleChange opens a pending role change that accumulates single-signer approvals. + // The change auto-applies once the role's authorization policy is satisfied. + ProposeRoleChange(context.Context, *MsgProposeRoleChange) (*MsgProposeRoleChangeResponse, error) + // ApproveRoleChange records a single-signer approval for an open pending role change. + // When the accumulated approvals satisfy the role's policy, the change is applied automatically. + ApproveRoleChange(context.Context, *MsgApproveRoleChange) (*MsgApproveRoleChangeResponse, error) + // CreateRegistryClass creates a new registry class that defines asset class-level authorization + // rules for role updates. The signer must match the maintainer address. + CreateRegistryClass(context.Context, *MsgCreateRegistryClass) (*MsgCreateRegistryClassResponse, error) + // UpdateRegistryClassRoleAuthorization replaces the authorization rules for an existing registry + // class. Only the current maintainer may update the rules. + UpdateRegistryClassRoleAuthorization(context.Context, *MsgUpdateRegistryClassRoleAuthorization) (*MsgUpdateRegistryClassRoleAuthorizationResponse, error) + // CancelRoleChange cancels an open pending role change. + // Only the original proposer may cancel. + CancelRoleChange(context.Context, *MsgCancelRoleChange) (*MsgCancelRoleChangeResponse, error) + // AssociateRegistryClass associates or updates the registry class for an existing registry entry + // without modifying any roles. The signer must be the CONTROLLER if one is set, or the scope + // data owner if the NFT is a Provenance Metadata Scope, or the NFT owner otherwise. + AssociateRegistryClass(context.Context, *MsgAssociateRegistryClass) (*MsgAssociateRegistryClassResponse, error) + // UpdateParams is a governance proposal endpoint for updating the registry module's params, + // including the default role authorization policies. The authority must be the governance module + // account address. + UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) RegisterNFT(ctx context.Context, req *MsgRegisterNFT) (*MsgRegisterNFTResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterNFT not implemented") +} +func (*UnimplementedMsgServer) GrantRole(ctx context.Context, req *MsgGrantRole) (*MsgGrantRoleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GrantRole not implemented") +} +func (*UnimplementedMsgServer) RevokeRole(ctx context.Context, req *MsgRevokeRole) (*MsgRevokeRoleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RevokeRole not implemented") +} +func (*UnimplementedMsgServer) UnregisterNFT(ctx context.Context, req *MsgUnregisterNFT) (*MsgUnregisterNFTResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UnregisterNFT not implemented") +} +func (*UnimplementedMsgServer) RegistryBulkUpdate(ctx context.Context, req *MsgRegistryBulkUpdate) (*MsgRegistryBulkUpdateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegistryBulkUpdate not implemented") +} +func (*UnimplementedMsgServer) SetRoles(ctx context.Context, req *MsgSetRoles) (*MsgSetRolesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetRoles not implemented") +} +func (*UnimplementedMsgServer) ProposeRoleChange(ctx context.Context, req *MsgProposeRoleChange) (*MsgProposeRoleChangeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProposeRoleChange not implemented") +} +func (*UnimplementedMsgServer) ApproveRoleChange(ctx context.Context, req *MsgApproveRoleChange) (*MsgApproveRoleChangeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ApproveRoleChange not implemented") +} +func (*UnimplementedMsgServer) CreateRegistryClass(ctx context.Context, req *MsgCreateRegistryClass) (*MsgCreateRegistryClassResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateRegistryClass not implemented") +} +func (*UnimplementedMsgServer) UpdateRegistryClassRoleAuthorization(ctx context.Context, req *MsgUpdateRegistryClassRoleAuthorization) (*MsgUpdateRegistryClassRoleAuthorizationResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateRegistryClassRoleAuthorization not implemented") +} +func (*UnimplementedMsgServer) CancelRoleChange(ctx context.Context, req *MsgCancelRoleChange) (*MsgCancelRoleChangeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CancelRoleChange not implemented") +} +func (*UnimplementedMsgServer) AssociateRegistryClass(ctx context.Context, req *MsgAssociateRegistryClass) (*MsgAssociateRegistryClassResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AssociateRegistryClass not implemented") +} +func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_RegisterNFT_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRegisterNFT) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RegisterNFT(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/RegisterNFT", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RegisterNFT(ctx, req.(*MsgRegisterNFT)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_GrantRole_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgGrantRole) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).GrantRole(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/GrantRole", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).GrantRole(ctx, req.(*MsgGrantRole)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_RevokeRole_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRevokeRole) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RevokeRole(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/RevokeRole", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RevokeRole(ctx, req.(*MsgRevokeRole)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UnregisterNFT_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUnregisterNFT) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UnregisterNFT(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/UnregisterNFT", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UnregisterNFT(ctx, req.(*MsgUnregisterNFT)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_RegistryBulkUpdate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRegistryBulkUpdate) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RegistryBulkUpdate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/RegistryBulkUpdate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RegistryBulkUpdate(ctx, req.(*MsgRegistryBulkUpdate)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_SetRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSetRoles) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).SetRoles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/SetRoles", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).SetRoles(ctx, req.(*MsgSetRoles)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_ProposeRoleChange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgProposeRoleChange) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).ProposeRoleChange(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/ProposeRoleChange", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).ProposeRoleChange(ctx, req.(*MsgProposeRoleChange)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_ApproveRoleChange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgApproveRoleChange) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).ApproveRoleChange(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/ApproveRoleChange", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).ApproveRoleChange(ctx, req.(*MsgApproveRoleChange)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_CreateRegistryClass_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateRegistryClass) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateRegistryClass(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/CreateRegistryClass", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateRegistryClass(ctx, req.(*MsgCreateRegistryClass)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateRegistryClassRoleAuthorization_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateRegistryClassRoleAuthorization) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateRegistryClassRoleAuthorization(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/UpdateRegistryClassRoleAuthorization", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateRegistryClassRoleAuthorization(ctx, req.(*MsgUpdateRegistryClassRoleAuthorization)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_CancelRoleChange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCancelRoleChange) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CancelRoleChange(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/CancelRoleChange", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CancelRoleChange(ctx, req.(*MsgCancelRoleChange)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_AssociateRegistryClass_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgAssociateRegistryClass) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).AssociateRegistryClass(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/AssociateRegistryClass", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).AssociateRegistryClass(ctx, req.(*MsgAssociateRegistryClass)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.registry.v1.Msg/UpdateParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + } + return interceptor(ctx, in, info, handler) +} + +var Msg_serviceDesc = _Msg_serviceDesc +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "provenance.registry.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "RegisterNFT", + Handler: _Msg_RegisterNFT_Handler, + }, + { + MethodName: "GrantRole", + Handler: _Msg_GrantRole_Handler, + }, + { + MethodName: "RevokeRole", + Handler: _Msg_RevokeRole_Handler, + }, + { + MethodName: "UnregisterNFT", + Handler: _Msg_UnregisterNFT_Handler, + }, + { + MethodName: "RegistryBulkUpdate", + Handler: _Msg_RegistryBulkUpdate_Handler, + }, + { + MethodName: "SetRoles", + Handler: _Msg_SetRoles_Handler, + }, + { + MethodName: "ProposeRoleChange", + Handler: _Msg_ProposeRoleChange_Handler, + }, + { + MethodName: "ApproveRoleChange", + Handler: _Msg_ApproveRoleChange_Handler, + }, + { + MethodName: "CreateRegistryClass", + Handler: _Msg_CreateRegistryClass_Handler, + }, + { + MethodName: "UpdateRegistryClassRoleAuthorization", + Handler: _Msg_UpdateRegistryClassRoleAuthorization_Handler, + }, + { + MethodName: "CancelRoleChange", + Handler: _Msg_CancelRoleChange_Handler, + }, + { + MethodName: "AssociateRegistryClass", + Handler: _Msg_AssociateRegistryClass_Handler, + }, + { + MethodName: "UpdateParams", + Handler: _Msg_UpdateParams_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "provenance/registry/v1/tx.proto", +} + +func (m *MsgRegisterNFT) 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 *MsgRegisterNFT) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterNFT) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintTx(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0x22 + } + if len(m.Roles) > 0 { + for iNdEx := len(m.Roles) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Roles[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.Key != nil { + { + size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRegisterNFTResponse) 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 *MsgRegisterNFTResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterNFTResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgGrantRole) 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 *MsgGrantRole) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantRole) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Addresses) > 0 { + for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Addresses[iNdEx]) + copy(dAtA[i:], m.Addresses[iNdEx]) + i = encodeVarintTx(dAtA, i, uint64(len(m.Addresses[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if m.Role != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Role)) + i-- + dAtA[i] = 0x18 + } + if m.Key != nil { + { + size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgGrantRoleResponse) 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 *MsgGrantRoleResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantRoleResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgRevokeRole) 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 *MsgRevokeRole) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeRole) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Addresses) > 0 { + for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Addresses[iNdEx]) + copy(dAtA[i:], m.Addresses[iNdEx]) + i = encodeVarintTx(dAtA, i, uint64(len(m.Addresses[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if m.Role != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Role)) + i-- + dAtA[i] = 0x18 + } + if m.Key != nil { + { + size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRevokeRoleResponse) 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 *MsgRevokeRoleResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeRoleResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUnregisterNFT) 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 *MsgUnregisterNFT) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUnregisterNFT) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Key != nil { + { + size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUnregisterNFTResponse) 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 *MsgUnregisterNFTResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUnregisterNFTResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgRegistryBulkUpdate) 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 *MsgRegistryBulkUpdate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegistryBulkUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Entries) > 0 { + for iNdEx := len(m.Entries) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Entries[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRegistryBulkUpdateResponse) 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 *MsgRegistryBulkUpdateResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegistryBulkUpdateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgSetRoles) 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 *MsgSetRoles) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetRoles) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RoleUpdates) > 0 { + for iNdEx := len(m.RoleUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoleUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.Key != nil { + { + size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgSetRolesResponse) 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 *MsgSetRolesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetRolesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgProposeRoleChange) 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 *MsgProposeRoleChange) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgProposeRoleChange) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RoleUpdates) > 0 { + for iNdEx := len(m.RoleUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoleUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.Key != nil { + { + size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgProposeRoleChangeResponse) 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 *MsgProposeRoleChangeResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgProposeRoleChangeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Applied { + i-- + if m.Applied { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if len(m.ChangeId) > 0 { + i -= len(m.ChangeId) + copy(dAtA[i:], m.ChangeId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ChangeId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgApproveRoleChange) 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 *MsgApproveRoleChange) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgApproveRoleChange) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChangeId) > 0 { + i -= len(m.ChangeId) + copy(dAtA[i:], m.ChangeId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ChangeId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgApproveRoleChangeResponse) 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 *MsgApproveRoleChangeResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgApproveRoleChangeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Applied { + i-- + if m.Applied { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgCancelRoleChange) 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 *MsgCancelRoleChange) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCancelRoleChange) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChangeId) > 0 { + i -= len(m.ChangeId) + copy(dAtA[i:], m.ChangeId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ChangeId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCancelRoleChangeResponse) 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 *MsgCancelRoleChangeResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCancelRoleChangeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgAssociateRegistryClass) 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 *MsgAssociateRegistryClass) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAssociateRegistryClass) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintTx(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0x1a + } + if m.Key != nil { + { + size, err := m.Key.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgAssociateRegistryClassResponse) 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 *MsgAssociateRegistryClassResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAssociateRegistryClassResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgCreateRegistryClass) 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 *MsgCreateRegistryClass) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateRegistryClass) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RoleAuthorizations) > 0 { + for iNdEx := len(m.RoleAuthorizations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoleAuthorizations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if len(m.Maintainer) > 0 { + i -= len(m.Maintainer) + copy(dAtA[i:], m.Maintainer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Maintainer))) + i-- + dAtA[i] = 0x22 + } + if len(m.AssetClassId) > 0 { + i -= len(m.AssetClassId) + copy(dAtA[i:], m.AssetClassId) + i = encodeVarintTx(dAtA, i, uint64(len(m.AssetClassId))) + i-- + dAtA[i] = 0x1a + } + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintTx(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateRegistryClassResponse) 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 *MsgCreateRegistryClassResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateRegistryClassResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUpdateRegistryClassRoleAuthorization) 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 *MsgUpdateRegistryClassRoleAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateRegistryClassRoleAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RoleAuthorizations) > 0 { + for iNdEx := len(m.RoleAuthorizations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoleAuthorizations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.RegistryClassId) > 0 { + i -= len(m.RegistryClassId) + copy(dAtA[i:], m.RegistryClassId) + i = encodeVarintTx(dAtA, i, uint64(len(m.RegistryClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) 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 *MsgUpdateRegistryClassRoleAuthorizationResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParams) 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 *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParamsResponse) 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 *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgRegisterNFT) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Roles) > 0 { + for _, e := range m.Roles { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRegisterNFTResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgGrantRole) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovTx(uint64(l)) + } + if m.Role != 0 { + n += 1 + sovTx(uint64(m.Role)) + } + if len(m.Addresses) > 0 { + for _, s := range m.Addresses { + l = len(s) + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgGrantRoleResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRevokeRole) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovTx(uint64(l)) + } + if m.Role != 0 { + n += 1 + sovTx(uint64(m.Role)) + } + if len(m.Addresses) > 0 { + for _, s := range m.Addresses { + l = len(s) + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgRevokeRoleResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUnregisterNFT) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUnregisterNFTResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRegistryBulkUpdate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Entries) > 0 { + for _, e := range m.Entries { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgRegistryBulkUpdateResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgSetRoles) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovTx(uint64(l)) + } + if len(m.RoleUpdates) > 0 { + for _, e := range m.RoleUpdates { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgSetRolesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgProposeRoleChange) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovTx(uint64(l)) + } + if len(m.RoleUpdates) > 0 { + for _, e := range m.RoleUpdates { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgProposeRoleChangeResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChangeId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Applied { + n += 2 + } + return n +} + +func (m *MsgApproveRoleChange) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ChangeId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgApproveRoleChangeResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Applied { + n += 2 + } + return n +} + +func (m *MsgCancelRoleChange) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ChangeId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgCancelRoleChangeResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgAssociateRegistryClass) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgAssociateRegistryClassResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgCreateRegistryClass) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.AssetClassId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Maintainer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.RoleAuthorizations) > 0 { + for _, e := range m.RoleAuthorizations { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgCreateRegistryClassResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateRegistryClassRoleAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RegistryClassId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.RoleAuthorizations) > 0 { + for _, e := range m.RoleAuthorizations { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Params.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgRegisterNFT) 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 ErrIntOverflowTx + } + 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: MsgRegisterNFT: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterNFT: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Roles", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Roles = append(m.Roles, RolesEntry{}) + if err := m.Roles[len(m.Roles)-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 RegistryClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RegistryClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRegisterNFTResponse) 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 ErrIntOverflowTx + } + 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: MsgRegisterNFTResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterNFTResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgGrantRole) 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 ErrIntOverflowTx + } + 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: MsgGrantRole: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantRole: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + } + m.Role = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Role |= RegistryRole(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgGrantRoleResponse) 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 ErrIntOverflowTx + } + 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: MsgGrantRoleResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantRoleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRevokeRole) 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 ErrIntOverflowTx + } + 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: MsgRevokeRole: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeRole: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + } + m.Role = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Role |= RegistryRole(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRevokeRoleResponse) 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 ErrIntOverflowTx + } + 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: MsgRevokeRoleResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeRoleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUnregisterNFT) 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 ErrIntOverflowTx + } + 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: MsgUnregisterNFT: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUnregisterNFT: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUnregisterNFTResponse) 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 ErrIntOverflowTx + } + 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: MsgUnregisterNFTResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUnregisterNFTResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRegistryBulkUpdate) 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 ErrIntOverflowTx + } + 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: MsgRegistryBulkUpdate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegistryBulkUpdate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Entries", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Entries = append(m.Entries, RegistryEntry{}) + if err := m.Entries[len(m.Entries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRegistryBulkUpdateResponse) 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 ErrIntOverflowTx + } + 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: MsgRegistryBulkUpdateResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegistryBulkUpdateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetRoles) 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 ErrIntOverflowTx + } + 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: MsgSetRoles: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetRoles: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RoleUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RoleUpdates = append(m.RoleUpdates, RoleUpdate{}) + if err := m.RoleUpdates[len(m.RoleUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetRolesResponse) 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 ErrIntOverflowTx + } + 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: MsgSetRolesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetRolesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgProposeRoleChange) 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 ErrIntOverflowTx + } + 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: MsgProposeRoleChange: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgProposeRoleChange: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Key == nil { + m.Key = &RegistryKey{} + } + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RoleUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RoleUpdates = append(m.RoleUpdates, RoleUpdate{}) + if err := m.RoleUpdates[len(m.RoleUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgProposeRoleChangeResponse) 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 ErrIntOverflowTx + } + 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: MsgProposeRoleChangeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgProposeRoleChangeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChangeId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChangeId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Applied", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Applied = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgApproveRoleChange) 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 ErrIntOverflowTx + } + 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: MsgApproveRoleChange: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgApproveRoleChange: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChangeId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChangeId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } -func (m *MsgRegisterNFT) Unmarshal(dAtA []byte) error { +func (m *MsgApproveRoleChangeResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1428,17 +5125,17 @@ func (m *MsgRegisterNFT) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRegisterNFT: wiretype end group for non-group") + return fmt.Errorf("proto: MsgApproveRoleChangeResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRegisterNFT: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgApproveRoleChangeResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Applied", wireType) } - var stringLen uint64 + var v int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1448,29 +5145,67 @@ func (m *MsgRegisterNFT) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + v |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx + m.Applied = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err } - postIndex := iNdEx + intStringLen - if postIndex < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } - if postIndex > l { + if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } - m.Signer = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCancelRoleChange) 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 ErrIntOverflowTx + } + 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: MsgCancelRoleChange: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCancelRoleChange: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1480,33 +5215,29 @@ func (m *MsgRegisterNFT) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - if m.Key == nil { - m.Key = &RegistryKey{} - } - if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Signer = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Roles", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ChangeId", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1516,25 +5247,23 @@ func (m *MsgRegisterNFT) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - m.Roles = append(m.Roles, RolesEntry{}) - if err := m.Roles[len(m.Roles)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.ChangeId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1557,7 +5286,7 @@ func (m *MsgRegisterNFT) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRegisterNFTResponse) Unmarshal(dAtA []byte) error { +func (m *MsgCancelRoleChangeResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1580,10 +5309,10 @@ func (m *MsgRegisterNFTResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRegisterNFTResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCancelRoleChangeResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRegisterNFTResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCancelRoleChangeResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -1607,7 +5336,7 @@ func (m *MsgRegisterNFTResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgGrantRole) Unmarshal(dAtA []byte) error { +func (m *MsgAssociateRegistryClass) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1630,10 +5359,10 @@ func (m *MsgGrantRole) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgGrantRole: wiretype end group for non-group") + return fmt.Errorf("proto: MsgAssociateRegistryClass: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgGrantRole: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgAssociateRegistryClass: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1705,27 +5434,8 @@ func (m *MsgGrantRole) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) - } - m.Role = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Role |= RegistryRole(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClassId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1753,7 +5463,7 @@ func (m *MsgGrantRole) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) + m.RegistryClassId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1776,7 +5486,7 @@ func (m *MsgGrantRole) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgGrantRoleResponse) Unmarshal(dAtA []byte) error { +func (m *MsgAssociateRegistryClassResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1799,10 +5509,10 @@ func (m *MsgGrantRoleResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgGrantRoleResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgAssociateRegistryClassResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgGrantRoleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgAssociateRegistryClassResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -1826,7 +5536,7 @@ func (m *MsgGrantRoleResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRevokeRole) Unmarshal(dAtA []byte) error { +func (m *MsgCreateRegistryClass) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1849,10 +5559,10 @@ func (m *MsgRevokeRole) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRevokeRole: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCreateRegistryClass: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRevokeRole: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCreateRegistryClass: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1889,9 +5599,9 @@ func (m *MsgRevokeRole) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClassId", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1901,33 +5611,29 @@ func (m *MsgRevokeRole) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - if m.Key == nil { - m.Key = &RegistryKey{} - } - if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.RegistryClassId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetClassId", wireType) } - m.Role = 0 + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1937,14 +5643,27 @@ func (m *MsgRevokeRole) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Role |= RegistryRole(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Maintainer", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1972,7 +5691,41 @@ func (m *MsgRevokeRole) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) + m.Maintainer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RoleAuthorizations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RoleAuthorizations = append(m.RoleAuthorizations, RoleAuthorization{}) + if err := m.RoleAuthorizations[len(m.RoleAuthorizations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -1995,7 +5748,7 @@ func (m *MsgRevokeRole) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRevokeRoleResponse) Unmarshal(dAtA []byte) error { +func (m *MsgCreateRegistryClassResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2018,10 +5771,10 @@ func (m *MsgRevokeRoleResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRevokeRoleResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCreateRegistryClassResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRevokeRoleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCreateRegistryClassResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -2045,7 +5798,7 @@ func (m *MsgRevokeRoleResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgUnregisterNFT) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateRegistryClassRoleAuthorization) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2068,10 +5821,10 @@ func (m *MsgUnregisterNFT) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUnregisterNFT: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateRegistryClassRoleAuthorization: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUnregisterNFT: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateRegistryClassRoleAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -2108,7 +5861,39 @@ func (m *MsgUnregisterNFT) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RegistryClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RegistryClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RoleAuthorizations", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2135,10 +5920,8 @@ func (m *MsgUnregisterNFT) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Key == nil { - m.Key = &RegistryKey{} - } - if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.RoleAuthorizations = append(m.RoleAuthorizations, RoleAuthorization{}) + if err := m.RoleAuthorizations[len(m.RoleAuthorizations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2163,7 +5946,7 @@ func (m *MsgUnregisterNFT) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgUnregisterNFTResponse) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateRegistryClassRoleAuthorizationResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2186,10 +5969,10 @@ func (m *MsgUnregisterNFTResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUnregisterNFTResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateRegistryClassRoleAuthorizationResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUnregisterNFTResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateRegistryClassRoleAuthorizationResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -2213,7 +5996,7 @@ func (m *MsgUnregisterNFTResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRegistryBulkUpdate) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2236,15 +6019,15 @@ func (m *MsgRegistryBulkUpdate) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRegistryBulkUpdate: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRegistryBulkUpdate: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2272,11 +6055,11 @@ func (m *MsgRegistryBulkUpdate) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Signer = string(dAtA[iNdEx:postIndex]) + m.Authority = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Entries", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2303,8 +6086,7 @@ func (m *MsgRegistryBulkUpdate) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Entries = append(m.Entries, RegistryEntry{}) - if err := m.Entries[len(m.Entries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2329,7 +6111,7 @@ func (m *MsgRegistryBulkUpdate) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgRegistryBulkUpdateResponse) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2352,10 +6134,10 @@ func (m *MsgRegistryBulkUpdateResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRegistryBulkUpdateResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRegistryBulkUpdateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: