LinkedResources
The linkedresources module enables accounts to attach, update, and remove arbitrary binary data ("linked resources") to an on‑chain Decentralised Identifier (DID) document. Each resource is versioned, signed by an authorised DID verification method, and subject to configurable size and length limits. In addition to resource management, the module provides parameter governance, rich gRPC/CLI queries, emitted events, a simulation framework, and CLI tooling.
Contents
Overview
The linkedresources module provides the following capabilities:
Create Linked Resource: Attach a new binary payload to an existing DID. Each resource is uniquely identified by
(did, id)
, typed via a string (type
), versioned (version ≥ 1
), and cryptographically signed by a DIDcapabilityInvocation
key.Update Linked Resource: Submit a new version of an existing resource. The
version
must increment by exactly 1, with a valid signature and respecting size/type limits. Only the latest version is stored on‑chain.Delete Linked Resource: Mark a resource as deleted. The on‑chain record remains for auditability; its
data
is zeroed, and its status changes toDELETED
.Parameter Governance: Network governance (via a designated authority) can update module parameters that govern data size and identifier length limits.
Rich Queries: gRPC and gRPC‑Gateway endpoints expose queries for parameters, single resources, all resources for a DID, or resources filtered by ID prefix.
Events: Typed events are emitted for create, update, delete, and parameter updates.
CLI Tools:
emped
commands for transactions and queries.Simulation: Weighted simulation operations for create, update, and delete flows.
Core Types
LinkedResource
message LinkedResource {
string id = 1; // Resource identifier
string did = 2; // Associated DID
bytes data = 3; // Raw payload
string type = 4; // MIME‑like type string
int64 version = 5; // Version number (≥1)
}
Represents the client‑facing payload and metadata for a linked resource.
LinkedResourceEntity
message LinkedResourceEntity {
bytes data = 1;
string type = 2;
int64 version = 3;
google.protobuf.Timestamp created_at = 4;
google.protobuf.Timestamp updated_at = 5; // nullable
LinkedResourceStatus status = 6;
}
Internal storage format, capturing raw data, version, timestamps, and status (ACTIVE
or DELETED
).
LinkedResourceRecord
message LinkedResourceRecord {
LinkedResource resource = 1;
google.protobuf.Timestamp created_at = 2;
google.protobuf.Timestamp updated_at = 3; // nullable
LinkedResourceStatus status = 4;
}
Returned by query endpoints, combining the core LinkedResource
with its creation/update timestamps and status.
Messages (Transactions)
All tx messages are defined under empe.linkedresources.Msg
.
CreateLinkedResource
rpc CreateLinkedResource(MsgCreateLinkedResource) returns (MsgCreateLinkedResourceResponse);
message MsgCreateLinkedResource {
string sender = 1; // Bech32 address
LinkedResource resource = 2;
Signature signature = 3; // { method_id, sig_bytes }
}
Validation:
sender
is valid,resource.Validate()
passes (non‑empty fields, version ≥1, allowed characters), sizes within params, DID exists and isACTIVE
, signature authorised and valid, resource not already present.Effects: Charges
createLinkedResource_<tier>
fee, stores asLinkedResourceEntity(status=ACTIVE)
, emitsEventCreateLinkedResource
.
UpdateLinkedResource
rpc UpdateLinkedResource(MsgUpdateLinkedResource) returns (MsgUpdateLinkedResourceResponse);
message MsgUpdateLinkedResource {
string sender = 1;
LinkedResource resource = 2; // same id & did, version = previous+1
Signature signature = 3;
}
Validation: Same checks as create, plus existing resource must be
ACTIVE
andresource.version = stored.version + 1
, signature valid.Effects: Charges
updateLinkedResource_<tier>
fee, updatesLinkedResourceEntity
(overwriting data, updating timestamps, keepingstatus=ACTIVE
), emitsEventUpdateLinkedResource
.
DeleteLinkedResource
rpc DeleteLinkedResource(MsgDeleteLinkedResource) returns (MsgDeleteLinkedResourceResponse);
message MsgDeleteLinkedResource {
string sender = 1;
DeleteLinkedResourcePayload payload = 2; // { did, id, version }
Signature signature = 3;
}
message DeleteLinkedResourcePayload {
string did = 1;
string id = 2;
int64 version = 3; // must match current version
}
Validation: Same identity checks, existing resource
ACTIVE
,payload.version
matches stored version, signature valid.Effects: Charges
deleteLinkedResource_<tier>
fee, stores entity with zeroeddata
,status=DELETED
, updated timestamp, emitsEventDeleteLinkedResource
.
UpdateParams
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);
message MsgUpdateParams {
string authority = 1; // must match configured authority
Params params = 2;
}
Validation:
authority
matches module authority,params.Validate()
passes (non‑zero limits).Effects: Persists new params, emits
EventUpdateParams
.
Queries
All queries under empe.linkedresources.Query
.
Params
rpc Params(QueryParamsRequest) returns (QueryParamsResponse);
message QueryParamsResponse { Params params = 1; }
CLI: emped query linkedresources params
LinkedResource
rpc LinkedResource(QueryLinkedResourceRequest) returns (QueryLinkedResourceResponse);
message QueryLinkedResourceResponse { LinkedResourceRecord linked_resource = 1; }
Fetch by DID and ID.
CLI: emped query linkedresources resource <did> <id>
LinkedResources
rpc LinkedResources(QueryLinkedResourcesRequest) returns (QueryLinkedResourcesResponse);
message QueryLinkedResourcesResponse {
repeated LinkedResourceRecord linked_resources = 1;
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
List all resources for a DID (paginated).
CLI: emped query linkedresources resources <did> [--limit N --page P]
LinkedResourcesByPrefix
rpc LinkedResourcesByPrefix(QueryLinkedResourcesByPrefixRequest) returns (QueryLinkedResourcesByPrefixResponse);
Filter resources whose id
starts with a given prefix. Supports pagination.
CLI: emped query linkedresources resources <did> --prefix <prefix> [--limit N --page P]
Events
EventCreateLinkedResource
sender
, did
, resource_id
, resource_type
, resource_size
EventUpdateLinkedResource
sender
, did
, resource_id
, version
, resource_type
, resource_size
EventDeleteLinkedResource
sender
, did
, resource_id
EventUpdateParams
authority
, params
(JSON‑encoded)
Parameters
Params
define module limits and defaults:
ResourceDataMaxSize
(int64): max bytes fordata
(default 64 KiB)ResourceIdMaxLength
(int64): max characters forid
(default 64)ResourceTypeMaxLength
(int64): max characters fortype
(default 32)
Modifiable via the MsgUpdateParams
transaction.
Genesis
The GenesisState
includes:
params
: initialParams
values.linked_resources
: a repeated list ofLinkedResourceRecord
entries (with resource payload, timestamps, and status).
On InitGenesis
, all entries are loaded into state with StoreLinkedResource
.
CLI Commands
Transaction Commands
emped tx linkedresources create-linked-resource <resource.json> <methodId> <sigBytes> --from <key>
emped tx linkedresources update-linked-resource <resource.json> <methodId> <sigBytes> --from <key>
emped tx linkedresources delete-linked-resource <did> <id> <version> <methodId> <sigBytes> --from <key>
Query Commands
emped query linkedresources params
emped query linkedresources resource <did> <id>
emped query linkedresources resources <did> [--prefix <prefix>] [--limit N --page P]
Simulation
Weighted operations registered for fuzz testing:
SimulateMsgCreateLinkedResource
(weight: 200)SimulateMsgUpdateLinkedResource
(weight: 100)SimulateMsgDeleteLinkedResource
(weight: 50)
These simulate DID document creation, resource operations, and fee handling.
Implementation Notes
Storage Layout: Keys stored as
<did>||0x00||<id>
under a module prefix for per‑DID iteration.Internal Types:
LinkedResourceEntity
for KV storage;LinkedResourceRecord
for queries.Fee Model: Fees named
createLinkedResource_<tier>
,updateLinkedResource_<tier>
, anddeleteLinkedResource_<tier>
based on DID tier.DID Integration: Signatures must be from a
capabilityInvocation
method in the DID document.Validation: Resources validated for format (
id/type
pattern) and size limits fromParams
.Errors: Defined errors include
ErrResourceTooLarge
,ErrInvalidSignature
,ErrLinkedResourceNotFound
, etc.
Last updated