Guides
Dash CoreDash PlatformDash.orgDash User DocsLog In
These docs are for v0.22.0. Click to read the latest docs for v0.25-redirect.

Identity Overview

Identities are a low-level construct that provide the foundation for user-facing functionality on the platform. An identity is a public key (or set of public keys) recorded on the platform chain that can be used to prove ownership of data. Please see the Identity DIP for additional information.

Identities consist of three components that are described in further detail in the following sections:

FieldTypeDescription
protocolVersionintegerThe protocol version
idarray of bytesThe identity id (32 bytes)
publicKeysarray of keysPublic key(s) associated with the identity
balanceintegerCredit balance associated with the identity
revisionintegerIdentity update revision

Each identity must comply with this JSON-Schema definition established in js-dpp:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "protocolVersion": {
      "type": "integer",
      "$comment": "Maximum is the latest protocol version"
    },
    "id": {
      "type": "array",
      "byteArray": true,
      "minItems": 32,
      "maxItems": 32,
      "contentMediaType": "application/x.dash.dpp.identifier"
    },
    "publicKeys": {
      "type": "array",
      "minItems": 1,
      "maxItems": 32,
      "uniqueItems": true
    },
    "balance": {
      "type": "integer",
      "minimum": 0
    },
    "revision": {
      "type": "integer",
      "minimum": 0,
      "description": "Identity update revision"
  }
},
  "required": [
    "protocolVersion",
    "id",
    "publicKeys",
    "balance",
    "revision"
  ]
}

Example Identity

{
  "protocolVersion": 0,
  "id": "4ZJsE1Yg8AosmC4hAeo3GJgso4N9pCoa6eCTDeXsvdhn",
  "publicKeys": [
    {
      "id": 0,
      "type": 0,
      "data": "Ao57Lp0174Svimn3OW+JUxOu/JhjhgRjBWzx9Gu/hyjo"
    }
  ],
  "balance": 0,
  "revision": 0
}

Identity id

The identity id is calculated by Base58 encoding the double sha256 hash of the outpoint used to fund the identity creation.

id = base58(sha256(sha256(<identity create funding output>)))

Note: The identity id uses the Dash Platform specific application/x.dash.dpp.identifier content media type. For additional information, please refer to the js-dpp PR 252 that introduced it and Identifier.js.

Identity publicKeys

The identity publicKeys array stores information regarding each public key associated with the identity. Each identity must have at least one public key.

Note: Since v0.22, the same public key can be used for multiple identities. In previous versions any public key(s) assigned to an identity had to be unique (not already used by any identity).

Each item in the publicKeys array consists of an object containing:

FieldTypeDescription
idintegerThe key id (all public keys must be unique)
typeintegerType of key (default: 0 - ECDSA)
dataarray of bytesPublic key (ECDSA: 33 bytes; BLS: 48 bytes)
purposeintegerPublic key purpose (0 - Authentication, 1 - Encryption, 2 - Decryption)
securityLevelintegerPublic key security level. (0 - Master, 1 - Critical, 2 - High, 3 - Medium)
readonlybooleanIdentity public key can't be modified with readOnly set to true. This can’t be changed after adding a key.

Each identity public key must comply with this JSON-Schema definition established in js-dpp:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "id": {
      "type": "integer",
      "minimum": 0,
      "description": "Public key ID",
      "$comment": "Must be unique for the identity. It can’t be changed after adding a key. Included when signing state transitions to indicate which identity key was used to sign."
    },
    "type": {
      "type": "integer",
      "enum": [
        0,
        1,
        2
      ],
      "description": "Public key type. 0 - ECDSA Secp256k1, 1 - BLS 12-381, 2 - ECDSA Secp256k1 Hash160",
      "$comment": "It can't be changed after adding a key"
    },
    "purpose": {
      "type": "integer",
      "enum": [
        0,
        1,
        2
      ],
      "description": "Public key purpose. 0 - Authentication, 1 - Encryption, 2 - Decryption",
      "$comment": "It can't be changed after adding a key"
    },
    "securityLevel": {
      "type": "integer",
      "enum": [
        0,
        1,
        2,
        3
      ],
      "description": "Public key security level. 0 - Master, 1 - Critical, 2 - High, 3 - Medium",
      "$comment": "It can't be changed after adding a key"
    },
    "data": true,
    "readOnly": {
      "type": "boolean",
      "description": "Read only",
      "$comment": "Identity public key can't be modified with readOnly set to true. It can’t be changed after adding a key"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "type": {
            "const": 0
          }
        }
      },
      "then": {
        "properties": {
          "data": {
            "type": "array",
            "byteArray": true,
            "minItems": 33,
            "maxItems": 33,
            "description": "Raw ECDSA public key",
            "$comment": "It must be a valid key of the specified type and unique for the identity. It can’t be changed after adding a key"
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "type": {
            "const": 1
          }
        }
      },
      "then": {
        "properties": {
          "data": {
            "type": "array",
            "byteArray": true,
            "minItems": 48,
            "maxItems": 48,
            "description": "Raw BLS public key",
            "$comment": "It must be a valid key of the specified type and unique for the identity. It can’t be changed after adding a key"
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "type": {
            "const": 2
          }
        }
      },
      "then": {
        "properties": {
          "data": {
            "type": "array",
            "byteArray": true,
            "minItems": 20,
            "maxItems": 20,
            "description": "ECDSA Secp256k1 public key Hash160",
            "$comment": "It must be a valid key hash of the specified type and unique for the identity. It can’t be changed after adding a key"
          }
        }
      }
    }
  ],
  "required": [
    "id",
    "type",
    "data",
    "purpose",
    "securityLevel"
  ],
  "additionalProperties": false
}

Public Key id

Each public key in an identity's publicKeys array must be assigned a unique index number (id).

Public Key type

The type field indicates the algorithm used to derive the key.

TypeDescription
0ECDSA Secp256k1 (default)
1BLS 12-381
2ECDSA Secp256k1 Hash160

Public Key data

The data field contains the compressed public key.

Example data encode/decode

Encode

// From the JavaScript reference implementation (js-dpp)
// AbstractStateTransitionIdentitySigned.js
pubKeyBase = new PublicKey({
  ...privateKeyModel.toPublicKey().toObject(),
  compressed: true,
})
  .toBuffer();

Decode

// From the JavaScript reference implementation (js-dpp)
// validatePublicKeysFactory.js
const dataHex = rawPublicKey.data.toString('hex');

Public Key purpose

The purpose field describes which operations are supported by the key. Please refer to DIP11 - Identities for additional information regarding this.

TypeDescription
0Authentication
1Encryption
2Decryption

Public Key securityLevel

The securityLevel field indicates how securely the key should be stored by clients. Please refer to DIP11 - Identities for additional information regarding this.

LevelDescriptionSecurity Practice
0MasterShould always require a user to authenticate when signing a transition
1CriticalShould always require a user to authenticate when signing a transition
2HighShould be available as long as the user has authenticated at least once during a session
3MediumShould not require user authentication but must require access to the client device

Public Key readOnly

The readOnly field indicates that the public key can't be modified if it is set to true. The value of this field cannot be changed after adding the key.

Identity balance

Each identity has a balance of credits established by value locked via a layer 1 lock transaction. This credit balance is used to pay the fees associated with state transitions.

Identity State Transition Details

There are two identity-related state transitions: identity create and identity topup. Details are provided in this section including information about asset locking and signing required for both state transitions.

Identity Creation

Identities are created on the platform by submitting the identity information in an identity create state transition.

FieldTypeDescription
protocolVersionintegerThe protocol version (currently 1)
typeintegerState transition type (2 for identity create)
assetLockProofobjectAsset lock proof object proving the layer 1 locking transaction exists and is locked
publicKeysarray of keysPublic key(s) associated with the identity
signaturearray of bytesSignature of state transition data (65 bytes)

Each identity must comply with this JSON-Schema definition established in js-dpp:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "protocolVersion": {
      "type": "integer",
      "$comment": "Maximum is the latest protocol version"
    },
    "type": {
      "type": "integer",
      "const": 2
    },
    "assetLockProof": {
      "type": "object"
    },
    "publicKeys": {
      "type": "array",
      "minItems": 1,
      "maxItems": 10,
      "uniqueItems": true
    },
    "signature": {
      "type": "array",
      "byteArray": true,
      "minItems": 65,
      "maxItems": 65
    }
  },
  "additionalProperties": false,
  "required": [
    "protocolVersion",
    "type",
    "assetLockProof",
    "publicKeys",
    "signature"
  ]
}

Example State Transition

{
  "protocolVersion":1,
  "type":2,
  "signature":"IBTTgge+/VDa/9+n2q3pb4tAqZYI48AX8X3H/uedRLH5dN8Ekh/sxRRQQS9LaOPwZSCVED6XIYD+vravF2dhYOE=",
  "assetLockProof":{
    "type":0,
    "instantLock":"AQHDHQdekbFZJOQFEe1FnRjoDemL/oPF/v9IME/qphjt5gEAAAB/OlZB9p8vPzPE55MlegR7nwhXRpZC4d5sYnOIypNgzfdDRsW01v8UtlRoORokjoDJ9hA/XFMK65iYTrQ8AAAAGI4q8GxtK9LHOT1JipnIfwiiv8zW+C/sbokbMhi/BsEl51dpoeBQEUAYWT7KRiJ4Atx49zIrqsKvmU1mJQza0Y1YbBSS/b/IPO8StX04bItPpDuTp6zlh/G7YOGzlEoe",
    "transaction":"0300000001c31d075e91b15924e40511ed459d18e80de98bfe83c5feff48304feaa618ede6010000006b483045022100dd0e4a6c25b1c7ed9aec2c93133f6de27b4c695a062f21f0aed1a2999fccf01c0220384aaf84cd5fd1c741fd1739f5c026a492abbfc18cfde296c6d90e98304f2f76012102fb9e87840f7e0a9b01f955d8eb4d1d2a52b32c9c43c751d7a348482c514ad222ffffffff021027000000000000166a14ea15af58c614b050a3b2e6bcc131fe0e7de37b9801710815000000001976a9140ccc680f945e964f7665f57c0108cba5ca77ed1388ac00000000",
    "outputIndex":0
  },
  "publicKeys":[
    {
      "id":0,
      "type":0,
      "purpose":0,
      "securityLevel":0,
      "data":"AkWRfl3DJiyyy6YPUDQnNx5KERRnR8CoTiFUvfdaYSDS",
      "readOnly":false
    }
  ]
}

Identity TopUp

Identity credit balances are increased by submitting the topup information in an identity topup state transition.

FieldTypeDescription
protocolVersionintegerThe protocol version (currently 1)
typeintegerState transition type (3 for identity topup)
assetLockProofobjectAsset lock proof object proving the layer 1 locking transaction exists and is locked
identityIdarray of bytesAn Identity ID for the identity receiving the topup (can be any identity) (32 bytes)
signaturearray of bytesSignature of state transition data (65 bytes)

Each identity must comply with this JSON-Schema definition established in js-dpp:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "protocolVersion": {
      "type": "integer",
      "$comment": "Maximum is the latest protocol version"
    },
    "type": {
      "type": "integer",
      "const": 3
    },
    "assetLockProof": {
      "type": "object"
    },
    "identityId": {
      "type": "array",
      "byteArray": true,
      "minItems": 32,
      "maxItems": 32,
      "contentMediaType": "application/x.dash.dpp.identifier"
    },
    "signature": {
      "type": "array",
      "byteArray": true,
      "minItems": 65,
      "maxItems": 65
    }
  },
  "additionalProperties": false,
  "required": [
    "protocolVersion",
    "type",
    "assetLockProof",
    "identityId",
    "signature"
  ]
}

Example State Transition

{
  "protocolVersion":1,
  "type":3,
  "signature":"IEqOV4DsbVa+nPipva0UrT0z0ZwubwgP9UdlpwBwXbFSWb7Mxkwqzv1HoEDICJ8GtmUSVjp4Hr2x0cVWe7+yUGc=",
  "identityId":"6YfP6tT9AK8HPVXMK7CQrhpc8VMg7frjEnXinSPvUmZC",
  "assetLockProof":{
    "type":0,
    "instantLock":"AQF/OlZB9p8vPzPE55MlegR7nwhXRpZC4d5sYnOIypNgzQEAAAAm8edm9p8URNEE9PBo0lEzZ2s9nf4u1SV0MaZyB0JTRasiXu8QtTmfqZWjI3qVtOpUhGPu6r/2fV+0Ffi3AAAAhA77E0aScf+5PTYzgV5WR6VJ/EnjvXyAMmAcu222JyvA7M+5OoCzVF/IQs2IWaPOFsRl1n5C+dMxdvrxhpVLT8QfZJSl19wzybWrHbGRaHDw4iWHvfYdwyXN+vP8UwDz",
    "transaction":"03000000017f3a5641f69f2f3f33c4e793257a047b9f0857469642e1de6c627388ca9360cd010000006b483045022100d8c383b15a3738d13b029605d242f041bea874cb4d0def1303ca7cdf76092bf102201b1d401ae9e8cdc5efc061249d2a967960dadce53c66e34d249c42049b48b26701210335b684aa510a9b54a3a4f79283e64482a323190045c239fae5ecb0450c78f965ffffffff02e803000000000000166a14f5383f51784bc4a27e2040bdd6cd9aae7fe6814d31690815000000001976a9144a0511ec3362b35983d0a101f0572dd26abce2ee88ac00000000",
    "outputIndex":0
  }
}

Asset Lock

The identity create and identity topup state transitions both include an asset lock proof object. This object references the layer 1 lock transaction and includes proof that the transaction is locked.

Currently there are two types of asset lock proofs: InstantSend and ChainLock. Transactions almost always receive InstantSend locks, so the InstantSend asset lock proof is the predominate type.

InstantSend Asset Lock Proof

The InstantSend asset lock proof is used for transactions that have received an InstantSend lock.

FieldTypeDescription
typeintegerThe asset lock proof type (0 for InstantSend locks)
instantLockarray of bytesThe InstantSend lock (islock)
transactionarray of bytesThe asset lock transaction
outputIndexintegerIndex of the transaction output to be used

Asset locks using an InstantSend lock as proof must comply with this JSON-Schema definition established in js-dpp:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "type": {
      "type": "integer",
      "const": 0
    },
    "instantLock": {
      "type": "array",
      "byteArray": true,
      "minItems": 165,
      "maxItems": 100000
    },
    "transaction": {
      "type": "array",
      "byteArray": true,
      "minItems": 1,
      "maxItems": 100000
    },
    "outputIndex": {
      "type": "integer",
      "minimum": 0
    }
  },
  "additionalProperties": false,
  "required": [
    "type",
    "instantLock",
    "transaction",
    "outputIndex"
  ]
}

ChainLock Asset Lock Proof

The ChainLock asset lock proof is used for transactions that have note received an InstantSend lock, but have been included in a block that has received a ChainLock.

FieldTypeDescription
typearray of bytesThe type of asset lock proof (1 for ChainLocks)
coreChainLockedHeightintegerHeight of the ChainLocked Core block containing the transaction
outPointobjectThe outpoint being used as the asset lock

Asset locks using a ChainLock as proof must comply with this JSON-Schema definition established in js-dpp:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "type": {
      "type": "integer",
      "const": 1
    },
    "coreChainLockedHeight":  {
      "type": "integer",
      "minimum": 1,
      "maximum": 4294967295
    },
    "outPoint": {
      "type": "array",
      "byteArray": true,
      "minItems": 36,
      "maxItems": 36
    }
  },
  "additionalProperties": false,
  "required": [
    "type",
    "coreChainLockedHeight",
    "outPoint"
  ]
}

Identity State Transition Signing

Note: The identity create and topup state transition signatures are unique in that they must be signed by the private key used in the layer 1 locking transaction. All other state transitions will be signed by a private key of the identity submitting them.

The process to sign an identity create state transition consists of the following steps:

  1. Canonical CBOR encode the state transition data - this include all ST fields except the signature
  2. Sign the encoded data with private key associated with a lock transaction public key
  3. Set the state transition signature to the value of the signature created in the previous step

Code snipits related to signing

// From js-dpp
// AbstractStateTransition.js
// toBuffer encodes the object (excluding the signature-related fields) with canonical CBOR
const data = this.toBuffer({ skipSignature: true });
const privateKeyModel = new PrivateKey(privateKey);

this.setSignature(sign(data, privateKeyModel));

// From dashcore-lib
// signer.js
/**
* @param {Buffer} data
* @param {string|PrivateKey} privateKey
* @return {Buffer}
*/
function sign(data, privateKey) {
	var hash = doubleSha(data);
	return signHash(hash, privateKey);
}

/**
* Sign hash.
* @param {Buffer} hash
* @param {string|PrivateKey} privateKey
* @return {Buffer} - 65-bit compact signature
*/
function signHash(hash, privateKey) {
	if (typeof privateKey === 'string') {
		privateKey = new PrivateKey(privateKey);
	}

	var ecdsa = new ECDSA();
	ecdsa.hashbuf = hash;
	ecdsa.privkey = privateKey;
	ecdsa.pubkey = privateKey.toPublicKey();
	ecdsa.signRandomK();
	ecdsa.calci();
	return ecdsa.sig.toCompact();
}