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

Data Contracts

Overview

Data contracts define the schema (structure) of data an application will store on Dash Platform. Contracts are described using JSON Schema which allows the platform to validate the contract-related data submitted to it.

The following sections provide details that developers need to construct valid contracts: documents and definitions. All data contracts must define one or more documents, whereas definitions are optional and may not be used for simple contracts.

General Constraints

🚧

Constraints

There are a variety of constraints currently defined for performance and security reasons. The following constraints are applicable to all aspects of data contracts. Unless otherwise noted, these constraints are defined in the platform's JSON Schema rules (e.g. js-dpp data contract meta schema).

Keyword

πŸ“˜

Dash Platform Protocol 0.20

Updating to the JSON Schema 2012-12 specification replaced the definitions keyword with the $defs keyword.

🚧

The $ref keyword has been temporarily disabled since Platform v0.22.

KeywordConstraint
defaultRestricted - cannot be used (defined in DPP logic)
propertyNamesRestricted - cannot be used (defined in DPP logic)
uniqueItems: truemaxItems must be defined (maximum: 100000)
pattern: <something>maxLength must be defined (maximum: 50000)
format: <something>maxLength must be defined (maximum: 50000)
$ref: <something>Temporarily disabled
$ref can only reference $defs -
remote references not supported
if, then, else, allOf, anyOf, oneOf, notDisabled for data contracts
dependenciesNot supported. Use dependentRequired and dependentSchema instead
additionalItemsNot supported. Use items: false and prefixItems instead
patternPropertiesRestricted - cannot be used for data contracts
patternAccept only RE2 compatible regular expressions (defined in DPP logic)

Data Size

Note: These constraints are defined in the Dash Platform Protocol logic (not in JSON Schema).

All serialized data (including state transitions) is limited to a maximum size of 16 KB.

Additional Properties

Although JSON Schema allows additional, undefined properties by default, they are not allowed in Dash Platform data contracts. Data contract validation will fail if they are not explicitly forbidden using the additionalProperties keyword anywhere properties are defined (including within document properties of type object).

Include the following at the same level as the properties keyword to ensure proper validation:

"additionalProperties": false

Documents

The documents object defines each type of document required by the data contract. At a minimum, a document must consist of 1 or more properties. Documents may also define indices and a list of required properties. The additionalProperties properties keyword must be included as described in the constraints section.

The following example shows a minimal documents object defining a single document (note) that has one property (message).

{
  "note": {
    "properties": {
      "message": {
        "type": "string"
      }
    },
    "additionalProperties": false
  }
}

Document Properties

The properties object defines each field that will be used by a document. Each field consists of an object that, at a minimum, must define its data type (string, number, integer, boolean, array, object). Fields may also apply a variety of optional JSON Schema constraints related to the format, range, length, etc. of the data.

🚧

Property type: object

The object type is required to have properties defined either directly or via the data contract's $defs. For example, the body property shown below is an object containing a single string property (objectProperty):

const contractDocuments = {
  message: {
    type: "object",
    properties: {
      body: {
        type: "object",
       properties: {
          objectProperty: {
            type: "string"
          },
        },
        additionalProperties: false,
      },
      header: {
        type: "string"
      }
    },
    additionalProperties: false
  }
};

πŸ“˜

JSON Schema

A full explanation of the capabilities of JSON Schema is beyond the scope of this document. For more information regarding its data types and the constraints that can be applied, please refer to the JSON Schema reference documentation.

Property Constraints

There are a variety of constraints currently defined for performance and security reasons.

DescriptionValue
Minimum number of properties1
Maximum number of properties100
Minimum property name length1 (Note: minimum length was 3 prior to v0.23)
Maximum property name length64
Property name charactersAlphanumeric (A-Z, a-z, 0-9)
Hyphen (-)
Underscore (_)

πŸ“˜

Note: Prior to Dash Platform v0.23 there were stricter limitations on minimum property name length and the characters that could be used in property names.

Required Properties (Optional)

Each document may have some fields that are required for the document to be valid and other fields that are optional. Required fields are defined via the required array which consists of a list of the field names from the document that must be present. The required object should be excluded for documents without any required properties.

"required": [
  "<field name a>",
  "<field name b>"
]

Example
The following example (excerpt from the DPNS contract's domain document) demonstrates a document that has 6 required fields:

"required": [
  "nameHash",
  "label",
  "normalizedLabel",
  "normalizedParentDomainName",
  "preorderSalt",
  "records"
],

Document Indices

πŸ“˜

The indices object should be excluded for documents that do not require indices.

Note: Dash Platform v0.23 only allows ascending default ordering for indices.

Document indices may be defined if indexing on document fields is required.

The indices array consists of:

  • One or more objects that each contain:
    • A unique name for the index
    • A properties array composed of a <field name: sort order> object for each document field that is part of the index (sort order: asc only for Dash Platform v0.23)
    • An (optional) unique element that determines if duplicate values are allowed for the document

🚧

Compound Indices

When defining an index with multiple properties (i.e a compound index), the order in which the properties are listed is important. Refer to the mongoDB documentation for details regarding the significance of the order as it relates to querying capabilities. Dash uses GroveDB which works similarly but does requiring listing all the index's fields in query order by statements.

"indices": [ 
  {
    "properties": [
      { "<field name a>": "<asc"|"desc>" },
      { "<field name b>": "<asc"|"desc>" }
    ], 
    "unique": true|false
  },
  {
    "properties": [
      { "<field name c>": "<asc"|"desc>" },
    ], 
  }    
]

Index Constraints

🚧

For performance and security reasons, indices have the following constraints. These constraints are subject to change over time.

DescriptionValue
Minimum/maximum length of index name1 / 32
Maximum number of indices10
Maximum number of unique indices3
Maximum number of properties in a single index10
Maximum length of indexed string property63
Note: Dash Platform v0.22+. does not allow indices for arrays
Maximum length of indexed byte array property
255
Note: Dash Platform v0.22+. does not allow indices for arrays
Maximum number of indexed array items
1024
Usage of $id in an index disallowedN/A

Example
The following example (excerpt from the DPNS contract's preorder document) creates an index on saltedDomainHash that also enforces uniqueness across all documents of that type:

"indices": [
  {
    "properties": [
      { "saltedDomainHash": "asc" }
    ],
    "unique": true
  }
],

Full Document Syntax

This example syntax shows the structure of a documents object that defines two documents, an index, and a required field.

{
  "<document name a>": {
    "type": "object",
    "properties": {
      "<field name b>": {
        "type": "<field data type>"
      },
      "<field name c>": {
        "type": "<field data type>"
      },
    },
    "indices": [
      {
        "name": "<index name>",
        "properties": [
          {
            "<field name c>": "asc"
          }
        ],
        "unique": true|false
      },
    ],
    "required": [
      "<field name c>"
    ]
    "additionalProperties": false
  },
  "<document name x>": {
    "type": "object",
    "properties": {
      "<property name y>": {
        "type": "<property data type>"
      },
      "<property name z>": {
        "type": "<property data type>"
      },
    },
    "additionalProperties": false
  },    
}

Definitions

The optional $defs object enables definition of aspects of a schema that are used in multiple places. This is done using the JSON Schema support for reuse. Items defined in $defs may then be referenced when defining documents through use of the $ref keyword.

πŸ“˜

Properties defined in the $defs object must meet the same criteria as those defined in the documents object.

❗️

Remote references blocked

Data contracts can only use the $ref keyword to reference their own $defs. Referencing external definitions is not supported by the platform protocol.

Example
The following example shows a definition for a message object consisting of two properties:

{
  // Preceeding content truncated ...
  "$defs": {
    "message": {
      "type": "object",
      "properties": {
        "timestamp": {
          "type": "number"
        },
        "description": {
          "type": "string"
        }
      },
      "additionalProperties": false
    }
  }
}

❗️

Toplevel definitions blocked by issue #185

Currently using definitions at the document toplevel throws an error. See https://github.com/dashevo/js-dpp/issues/185

πŸ“˜

Adding $defs with js-dpp

In the js-dpp reference implementation, definitions are added to a data contract via the .setDefinitions() method (e.g. myContract.setDefinitions({"message": { ... }}). This must be done prior to broadcasting the contract for registration.

For a code example for setting definitions using js-dpp see this gist