This ADR defines the cheqd DID method and describes the identity entities, queries, and transaction types for the cheqd network: a purpose-built self-sovereign identity (SSI) network based on the Cosmos blockchain framework.
Decentralized identifiers (DIDs) are a type of identifier that enables verifiable, decentralized digital identity. A DID refers to any subject (for example, a person, organization, thing, data model, abstract entity, and so on) as determined by the controller of the DID.
Hyperledger Indy is a verifiable data registry (VDR) built for DIDs with a strong focus on privacy-preserving techniques. It is one of the most widely-adopted SSI blockchain ledgers. Most notably, Indy is used by the Sovrin Network.
The Sovrin Foundation initiated a project called libsovtoken
in 2018 to create a native token for Hyperledger Indy. libsovtoken
was intended to be a payment handler library that could work with libindy
and be merged upstream. This native token would allow interactions on Hyperledger Indy networks (such as Sovrin) to be paid for using tokens.
Due to challenges the project ran into, the libsovtoken
codebase saw its last official release in August 2019.
The cheqd network aims to support similar use cases for SSI as seen on Hyperledger Indy networks, with a similar focus on privacy-resspecting techniques.
Since the core of Hyperledger Indy's architecture was designed before the W3C DID specification started to be defined, the Indy DID Method (did:indy
) has aspects that are not fully-compliant with latest specifications.
However, the rationale for why the cheqd team chose the Cosmos blockchain framework instead of Hyperledger Indy were primarily down to the following reasons:
Hyperledger Indy is a permissioned ledger: Indy networks are permissioned networks where the ability to have write capability is restricted to a limited number of nodes. Governance of such a permissioned network is therefore also not decentralised.
Limitations of Hyperledger Indy's consensus mechanism: Linked to the permissioned nature of Indy are the drawbacks of its Plenum Byzantine Fault Tolerant (BFT) consensus mechanism, which effectively limits the number of nodes with write capability to approximately 25 nodes. This limit is due to limited transactions per second (TPS) for an Indy network with a large number of nodes, rather than a hard cap implemented in the consensus protocol.
Wider ecosystem for token functionality outside of Hyperledger Indy: Due to its origins as an identity-specific ledger, Indy does not have a fully-featured token implementation with sophisticated capabilities. Moreover, this also impacts end-user options for ecosystem services such as token wallets, cryptocurrency exchanges, custodianship services etc that would be necessary to make a viable, enterprise-ready SSI ledger with token functionality.
By selecting the Cosmos blockchain framework, the maintainers of the cheqd project aim to address the limitations of Hyperledger Indy outlined above. However, with an eye towards interoperability, the cheqd project aims to use Hyperledger Aries for ledger-related peer-to-peer interactions.
Our aim is to support the functionality enabled by identity-domain transactions in by Hyperledger Indy into cheqd-node
. This will partly enable the goal of allowing use cases of existing SSI networks on Hyperledger Indy to be supported by the cheqd network.
The following identity-domain transactions from Indy were considered:
NYM
: Equivalent to "DIDs" on other networks
ATTRIB
: Payload for DID Document generation
SCHEMA
: Schema used by a credential
CRED_DEF
: Credential definition by an issuer for a particular schema
REVOC_REG_DEF
: Credential revocation registry definition
REVOC_REG_ENTRY
: Credential revocation registry entry
Revocation registries for credentials are not covered under the scope of this ADR. This topic is discussed separately in a future ADR as there is ongoing research by the cheqd project on how to improve the privacy and scalability of credential revocations.
Schemas and Credential Definitions are also not covered under the scope of this ADR. Their implementation is covered in ADR 002: DID-Linked Resources.
did:cheqd
)The method-name
for the cheqd DID Method will be identified by the string cheqd
.
A DID that uses the cheqd DID method MUST begin with the prefix did:cheqd
. This prefix string MUST be in lowercase. The remainder of the DID, after the prefix, is as follows:
The cheqd DID method's method-specific identifier (method-specific-id
) is made up of the namespace
component. The namespace
is defined as a string that identifies the cheqd network (e.g., "mainnet", "testnet") where the DID reference is stored. Different cheqd networks may be differentiated based on whether they are production vs non-production, governance frameworks in use, participants involved in running nodes, etc.
The namespace
associated with a certain network/ledger is stored in the genesis file on the node and cannot be changed by validators vote. A namespace is optional and can be omitted.
A did:cheqd
DID must be unique. The syntax of the unique-id
component may be defined as a Universally Unique Identifier (UUID) generated by the creator(s) of the DID. UUIDs are the preferred unique identifier format for cheqd network.
Usage of UUID-style identifiers significantly simplifies the generation and implementation of unique identifiers, with extremely-low probability of a collission where the same UUID is generated independently.
Any client application can generate these UUIDs using their own preferred implementation in any programming language, as opposed to the method-specific logic required for Indy-style DID identifiers.
Alternatively, the unique-id
may also be generated similar to the did:indy method
from the initial public key of the DID (e.g., base58 encoding of the first 16 bytes of the SHA256 of the first Verification Method Ed25519
public key). This unique-id
format is referred to as the "Indy-style" unique identifier in our documentation.
Support for Indy-style unique identifiers makes compatibility with Indy-based client SDKs, such as those based on Hyperledger Aries.
If no namespace
is specified, it assumed to be default namespace
for the network/ledger the request is targetted at. This will generally be mainnet
for the primary production cheqd network.
did:cheqd
methodThe cheqd DID method ABNF to conform with DID syntax guidelines is as follows:
Note: The
*id-char unique-id
must be 16 bytes of Indy-style base58 encoded identifier.
Where the formal definition of UUIDs is represented using this ABNF:
did:cheqd
identifiersA DID written to the cheqd "mainnet" ledger namespace
with an Indy-style identifier:
A DID written to the cheqd "testnet" ledger namespace
with an Indy-style identifier:
An Indy-style DID where no namespace is defined, where the namespace
would default to the one defined on ledger where it's published (typically, mainnet
):
A UUID-style DID on cheqd "mainnet" namespace
:
A UUID-style DID where no namespace is defined, where the namespace
would default to the one defined on ledger where it's published (typically, mainnet
):
A DID Document ("DIDDoc") associated with a cheqd DID is a set of data describing a DID subject. The representation of a DIDDoc when requested for production from a DID on cheqd networks MUST meet the DID Core specifications.
The following elements are needed for a W3C specification compliant DIDDoc representation:
@context
(optional): A list of strings with links or JSONs for describing specifications that this DID Document is following to.
id
: Target DID with cheqd DID Method prefix did:cheqd:<namespace>:
and a unique-id
identifier.
controller
(optional): A list of fully qualified DID strings or one string. Contains one or more DIDs who can update this DIDdoc. All DIDs must exist.
verificationMethod
(optional): A list of Verification Methods
authentication
(optional): A list of strings with key aliases or IDs
assertionMethod
(optional): A list of strings with key aliases or IDs
capabilityInvocation
(optional): A list of strings with key aliases or IDs
capabilityDelegation
(optional): A list of strings with key aliases or IDs
keyAgreement
(optional): A list of strings with key aliases or IDs
service
(optional): A set of Service Endpoint maps
alsoKnownAs
(optional): A list of strings. A DID subject can have multiple identifiers for different purposes, or at different times. The assertion that two or more DIDs refer to the same DID subject can be made using the alsoKnownAs
property.
"diddoc:<id>" -> {DIDDoc, DidDocumentMetadata, txHash, txTimestamp }
didDocumentMetadata
is created by the node after transaction ordering and before adding it to a state.
Each DID Document MUST have a metadata section when a representation is produced. It can have the following properties:
created
(string): Formatted as an XML Datetime normalized to UTC 00:00:00 and without sub-second decimal precision, e.g., 2020-12-20T19:17:47Z
.
updated
(string): The value of the property MUST follow the same formatting rules as the created property. The updated
field is null
if an Update operation has never been performed on the DID document. If an updated property exists, it can be the same value as the created property when the difference between the two timestamps is less than one second.
deactivated
(string): If DID has been deactivated, DID document metadata MUST include this property with the boolean value true
. By default this is set to false
.
versionId
(string): A UUID string that represents the version identifier of the DID Document.
resources
(list of resources metadata referred to as Resource previews)| optional. Cannot be changed by CreateDID or UpdateDID transactions. cheqd ledger stores only the resource identifiers in the DID Doc metadata. The remainder of the resources' metadata is added when a DID is resolved.
previousVersionId
(string): A UUID string that represents the version identifier of the previous version of the DID Document. The previousVersionId
field is an empty string if an Update operation has never been performed on the DID document
nextVersionId
(string): A UUID string that represents the version identifier of the next version of the DID Document. The nextVersionId
field is an empty string if an Update operation has never been performed on the DID document