Po.et is a decentralized event-sourced system. Events can be made up of any data, and they are anchored to the blockchain in the form of claims.
- Interoperable with any blockchain
- Interoperable with any storage mechanism (initially stored on IPFS)
- Batchable in arbitrary batch sizes and intervals to minimize transaction costs
- Performant enough to handle real-time streaming of claims from many different applications
- Support for arbitrary timing precision
Claims can have any information at all, but must include:
id
- A URI containing the hash of the claim contents, excluding the signature and id fieldstype
- A URI or an array of URIs referencing one or more type specificationsissuer
- A URI referencing the identity (person or orginazition) making the claimissuanceDate
- The date the claim was made (can be compared to current atomic time and potentially rejected if it is too far in the past), recorded as an ISO 8601 string in UTC timeclaim
- An object containing properties for the claim being madesec:proof
- A Linked Data Signature objecttype
- A URI that identifies the digital signature suite that was used to create the signature. Often, just the signature suite name (e.g. RsaSignature2018) is required from developers to initiate the creation of a signature.creator
- A URI that identifies the public/private key pair associated with the signature.The URI SHOULD be a URL that can be dereferenced to obtain a linked data document that contains a link identifying the entity that owns the key pair. Dereferencing the entity link SHOULD result in a Linked Data document that contains a link back to the URL identifier for the public/private key pair, thereby proving ownership.proofValue
- The signature, signing the entire claim, excluding theid
andsignature
fields, except for nonce.created
- The string value of an ISO8601 combined date and time string generated by the Signature Algorithm.nonce?
- Optional, but strongly recommended. A string value that is included in the digital signature and MUST only be used once for a particular domain and window of time. This value is used to mitigate replay attacks.domain?
- A string value specifying the restricted domain of the signature.
For example, a claim could look like this:
{
'@context': {
cred: 'https://w3id.org/credentials#',
dc: 'http://purl.org/dc/terms/',
schema: 'http://schema.org/',
sec: 'https://w3id.org/security#',
id: 'sec:digestValue',
issuer: 'cred:issuer',
issuanceDate: 'cred:issued',
type: 'schema:additionalType',
claim: 'schema:CreativeWork',
archiveUrl: 'schema:url',
author: 'schema:author',
canonicalUrl: 'schema:url',
contributors: {
'@id': 'schema:ItemList',
'@container': '@list',
'@type': 'schema:contributor',
},
copyrightHolder: 'schema:copyrightHolder',
dateCreated: 'schema:dateCreated',
datePublished: 'schema:datePublished',
license: 'schema:license',
name: 'schema:name',
tags: 'schema:keywords',
hash: 'sec:digestValue',
},
id: 'f4b3e6cd7e516211d1b718b84860d26f59e3933c03c25c29d4e9ce9cc34ff26b',
type: ClaimType.Work,
issuer:
'data:;base64,eyJhbGdvcml0aG0iOiJFZDI1NTE5U2lnbmF0dXJlMjAxOCIsInB1YmxpY0tleSI6IkdhRWZ2QURLQUw1ZXVWQjZxZ2p1djlnMkxoOVBhM2FuWkxLZjRnUlFvWVM0In0=',
issuanceDate: '2018-10-12T01:54:11.559Z',
claim: {
name: 'A Study in Scarlet',
author: 'Arthur Conan Doyle',
tags: 'detective novel, detective',
dateCreated: '1886-01-01T00:00:00.000Z',
datePublished: '1887-01-01T00:00:00.000Z',
},
'sec:proof': {
'@graph': {
'@type': 'sec:Ed25519Signature2018',
'dc:created': {
'@type': 'http://www.w3.org/2001/XMLSchema#dateTime',
'@value': '2018-10-12T01:54:11Z',
},
'dc:creator': {
'@id':
'data:;base64,eyJhbGdvcml0aG0iOiJFZDI1NTE5U2lnbmF0dXJlMjAxOCIsInB1YmxpY0tleSI6IkdhRWZ2QURLQUw1ZXVWQjZxZ2p1djlnMkxoOVBhM2FuWkxLZjRnUlFvWVM0In0=',
},
'sec:jws':
'eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19.._qJsUa-caH8BLds4rVLV9GuMEqxUlw6VRyfXN23Z0KHgtnJIiTnXoSzuwFF_rnIicza94Ggh5xkGAT4hZcrwBQ',
'sec:nonce': 'cjn5czg1u0000mnc93s13ihuz',
},
},
}
The issuer
field contains the public part of a key pair you own. You'll need the corresponding private key to prove
this claim was generated by you. Use @poet/poet-js
to generate an appropriate issuer from your private key.
The sec:proof
must be set to the result of cryptographically signing the claim with the private key you own using jsonld-signatures with the ED25519 eliptical curve. This signature is currently being validated with jsonld-signatures.verify, and we're using jsonld-signatures.sign to sign claims.
The id
field is the sha256
of the canonicalized claim, excluding the id
and sec:proof
fields, so getId(claim) == getId(getId(claim))
. We're using DigitalBazaar's jsonld implementation of JSON-LD in order to serialize the claims to a byte buffer deterministically and hashing this byte buffer.
We use URIs to resolve identities and references for now, pending investigation and progress into the DID specification. Lots of existing developer tools already know how to resolve URIs, which will maximize our ability to take advantage of already existing tools.