Content Objects
Content objects are the main way tenants store and retrieve data, globally referenced by (TenantId, ConqId)
.
They are created by storing data in a node, who calls CommitVersion with a digest of the data.
Once the verison is commited, other nodes in the space can retrieve the content object.
Once a sufficient number of nodes retrieve copies of the content object1, the original authoring node submits a ConfirmVersion which marks the commit as finalized.
Each content object also has a 'head' version which refers to the version that should be retrieved when a content object is referred to by its ID.
In order to prevent nodes from creating arbitrary versions without permission of tenants, a tenant-signed version commit message (VersionCommitMessage
) must be provided in the CommitVersion call.
VersionCommitMessage {
originator: ProviderId,
tenant_id: TenantId,
content_object_id: ContentObjectId,
version_id: VersionId,
tlp_size: #[compact] u64,
ts: u64,
set_head_on_finalize: bool,
kms_id: KMSId,
}
Content Object Lifecycle
flowchart TB dc(Draft Created) md(Modify Draft) df(Draft Finalized) cv(Version Commited) vp(Version Publishing) vf(Version Finalized) dc -->|tenant user creates draft on node| md md --->|tenant user modifies draft| md md -->|tenant user finalizes draft| df df -->|node calls CommitVersion| cv cv -->|node starts publishing parts to other fabric nodes| vp vp -->|parts receieved other nodes, node calls FinalizeVersion| vf
Content Types
TODO: Discuss
Content Object Blockchain Storage
(TenantId, ContentObjectId) -> {
head_version: Option<VersionId>,
version_count: u32,
}
(TenantId, ContentObjectId, VersionId) -> {
originator: ProviderId,
tlp_size: #[compact] u64,
ts_committed: u64,
ts_finalized: Option<u64>,
set_head_on_finalize: bool,
kms_id: KMSId
}
Content Object Blockchain Calls
-
CreateContentObject(origin: Origin, ten: TenantId, cobj: ContentObjectId)
- Checks that
origin
has at leastCONTENT
permissions inten
- Stores the content object at
(ten, cobj)
{ head_version: None, version_count: 0, }
- Checks that
-
CommitVersion(origin: Origin, tenant_signer: AccountId, vcm: VersionCommitMessage, vcm_sig: Signature)
- Checks that
origin
hasNODE
level permission withinvcm.provider_id
- Checks that
tenant_signer
hasCONTENT
level permission withinvcm.tenant_id
- Checks that
vcm_sig
is a valid signature of the scale encodedvcm
bytenant_signer
- Increment
version_count
at(vcm.tenant_id, vcm.content_object_id)
- Stores the version at
(vcm.tenant_id, vcm.content_object_id, vcm.version_id)
{ originator: vcm.originator, tlp_size: vcm.tlp_size, ts_committed: vcm.ts, ts_finalized: None, set_head_on_finalize: vcm.set_head_on_finalize, kms_id: vcm.kms_id, }
- Checks that
-
FinalizeVersion(origin: Origin, provider: ProviderId, ten: TenantId, cobj: ContentObjectId, ver: CObjVersionId, ts: u64)
- Checks that
origin
has at least node level withinprovider
. - Retrieve the version metadata,
ver_meta
, stored at(ten, cobj, ver)
- Checks that
provider
matches thever_meta.originator
- Checks that
ts
is a recent timestamp - Sets
ver_meta.ts_finalized = Some(ts)
- If
ver_meta.set_head_on_finalize
, sets thehead_version
of the content object at(ten, cobj)
tover
- Checks that
-
SetHeadVersion(origin: Origin, ten: TenantId, cobj: ContentObjectId, ver: Option<VersionId>)
- Checks that
origin
hasCONTENT
level permissions withinten
- Checks that
(ten, cobj, ver)
exists - Sets the
head_version
at(ten, cobj)
tover
- Checks that
-
DeleteVersion(origin: Origin, ten: TenantId, cobj: ContentObjectId, ver: VersionId)
- Checks that
origin
hasCONTENT
level permissions withinten
- Checks that
(ten, cobj, ver)
exists - Checks that
head_version
at(ten, cobj)
is notver
- Deletes the version stored at
(ten, cobj, ver)
- Decrements
version_count
at(ten, cobj)
- Checks that
-
DeleteContentObject(origin: Origin, ten: TenantId, cobj: ContentObjId)
- Checks that
origin
hasCONTENT
level permissions withinten
- Checks that
version_count
is0
- Deletes the content object at
(ten, cobj)
- Checks that
1 TODO: Should also talk about partitioning and how we assert data is replicated