CIP-8: Tile Document
Author | Joel Thorstensson |
---|---|
Discussions-To | https://github.com/ceramicnetwork/CIP/issues/56 |
Status | Final |
Category | RFC |
Created | 2020-07-22 |
Requires | 5 |
Table of Contents
Simple Summary
This CIP describes the Tile document which is a very general stream type that has JSON as its content and is controlled by a DID.
Abstract
The Tile document allows DIDs to create simple JSON documents that use json-patch for updating the content of the document. Each Tile is owned by a DID, which needs to sign the DataEvent. The DataEvents are encoded using dag-jose which allows the signatures to be natively encoded directly in IPLD. Tiles also support adding schemas to the document which means that the json data within the content of the document can be enforced to have a specific format.
Motivation
The Tile document is a very generic stream type that gives developers flexibility in how they structure the data that they put into Ceramic. While other stream types might have certain restrictions around what type of data is allowed to be stored and what the structure of that data should be, tiles allows any type of JSON data to be stored and updated. Tiles can be owned and controlled by any DID that implements the DID Provider specification. This provides the entire Decentralized Identity ecosystem with an interoperable verifiable document network.
Specification
Below the event formats and state transitions of the Tile document are specified. Together they should include all information needed to implement this stream type in Ceramic.
StreamID code: 0x00
Event formats
The InitEvent has the following required properties:
data
- the initial JSON content of the documentowners
- the owners array in the header needs to contain only DID strings
In addition to the required properties above the InitEvent may inlcude schema
, tags
, and unique
. The unique
property should include randomness as a string to ensure that there is no other document that is exactly the same.
Finally the InitEvent is signed and encoded using dag-jose.
The InitEvent can also be stored without a signature using dag-cbor. However in this case the data
property MUST be set to null
.
DataEvents of a Tile document are encoded using dag-jose. Other than that they conform to the standard event format. The content of the data
property should be a json-patch object which contains the difference from the previous document content state.
State transitions
Below the state transition logic for the three different supported events is described.
Applying the InitEvent
When the InitEvent is applied a StreamState
object is created that looks like this:
{
doctype: 'tile',
metadata: {
owners: initEvent.owners,
schema: initEvent.schema,
family: initEvent.family,
tags: initEvent.tags
},
content: initEvent.data,
signature: SignatureStatus.SIGNED,
anchorStatus: AnchorStatus.NOT_REQUESTED,
log: [new CID(initEvent)]
}
In addition to this, the following should be verified:
- If the event uses the dag-cbor format (not signed),
initEvent.data
MUST equalnull
owners
is an array of DID strings- If
schema
is defined it should be Ceramic StreamId string - If
tags
is defined it should be an array of strings content
should be JSON- If
schema
is defined the data in thecontent
should be valid according to the schema - The dag-jose signature should be valid and signed by the DID(s) in the
owners
array
Applying a DataEvent
When a DataEvent is applied the StreamState
object should be modified in the following way:
state.next = {
content: applyJSONPatch(state.content, dataEvent.data),
metadata: {
schema: dataEvent.schema,
family: initEvent.family,
tags: dataEvent.tags
}
}
state.signature = SignatureStatus.SIGNED
state.anchorStatus = AnchorStatus.NOT_REQUESTED
state.log.push(new CID(dataEvent))
Where applyJSONPatch
is a function that applies a json-patch and returns a new json object. In addition the following should be validated:
- If
schema
is defined it should be Ceramic StreamId string - If
tags
is defined it should be an array of strings - If
schema
is defined the data in thecontent
should be valid according to the schema - The dag-jose signature should be valid and signed by the DID(s) in the
owners
array in themetadata
property (not thenext.metadata
property of the state) - The dag-jose signature should include a
kid
property in it’s header which specifies thekeyFragment
as well as theversion-id
of the public key that was used to sign the event
Applying an TimeEvent
When an TimeEvent is applied the StreamState
object should be modified in the following way:
state.anchorStatus = AnchorStatus.ANCHORED
state.anchorProof = timeEvent.proof
state.content = state.next.content
state.metadata = Object.assign(state.metadata, state.next.metadata)
delete state.next
state.log.push(new CID(timeEvent))
No additional validation needs to happen at this point in the state transition function.
Rationale
The Tile specification provides a fairly straightforward way of implementing a general JSON document in Ceramic. By allowing a schema to be defined, the content of the document can be constrained. This gives developers both flexibility and control. There should not really be anything in this specification that is controversial.
Implementation
A reference implementation of the Tile document is provided in js-ceramic (see the stream-tile
package).
Security Considerations
Because of the double spend problem, a change of owners
is a trusted operation. This means that the new owner has to trust that the previous owner is not withholding the data of another owner change event that was anchored earlier. If the first owner publishes this event at a later point the document would change owner away from the new owner. In future versions of the Ceramic protocol it will be possible to specify an NFT as an owner of a document which means that the ownership transfer can happen on-chain and thus sidestep this problem.
Copyright
Copyright and related rights waived via CC0.
Citation
Please cite this document as:
Joel Thorstensson, "CIP-8: Tile Document," Ceramic Improvement Proposals, no. 8, July 2020. [Online serial]. Available: https://github.com/ceramicnetwork/CIPs/blob/main/CIPs/cip-8.md