diff --git a/docs/explanations/platform-protocol-state-transition.md b/docs/explanations/platform-protocol-state-transition.md index b2b2b20be..d237bcd59 100644 --- a/docs/explanations/platform-protocol-state-transition.md +++ b/docs/explanations/platform-protocol-state-transition.md @@ -36,7 +36,7 @@ The following table contains a list of currently defined payload types: | Payload Type | Payload Description | | - | - | -| [Data Contract Create](../protocol-ref/data-contract.md#data-contract-creation) (`0`) | [Database schema](../explanations/platform-protocol-data-contract.md) for a single application | +| [Data Contract Create](../protocol-ref/data-contract.md#data-contract-create) (`0`) | [Database schema](../explanations/platform-protocol-data-contract.md) for a single application | | [Batch](../protocol-ref/document.md#document-submission) (`1`) | An array of 1 or more [document](../explanations/platform-protocol-document.md) or token transition objects | | [Identity Create](../protocol-ref/identity.md#identity-create) (`2`) | Information including the public keys required to create a new [Identity](../explanations/identity.md) | | [Identity Topup](../protocol-ref/identity.md#identity-topup) (`3`) | Information including proof of a transaction containing an amount to add to the provided identity's balance | diff --git a/docs/protocol-ref/data-contract-document.md b/docs/protocol-ref/data-contract-document.md new file mode 100644 index 000000000..7dc97a4e8 --- /dev/null +++ b/docs/protocol-ref/data-contract-document.md @@ -0,0 +1,371 @@ +# Contract Documents + +## Contract Document Overview + +The `documents` object defines each type of document in the data contract. At a minimum, a document must consist of 1 or more properties. The `additionalProperties` properties keyword must be included as described in the [constraints](./data-contract.md#additional-properties) section and each property must be [assigned a position](#assigning-position). + +The following example shows a minimal `documents` object defining a single document (`note`) with one property (`message`). + +```json +{ + "note": { + "type": "object", + "properties": { + "message": { + "type": "string", + "position": 0 + } + }, + "additionalProperties": false + } +} +``` + +Documents may also define [indices](#document-indices), a list of [required](#required-properties) or [transient](#transient-properties) properties, and a custom [configuration](#document-configuration). Refer to this table for a brief description of the major document sections: + +| Feature | Description | +|------------|-----------------------------------------------| +| [Configuration](#document-configuration) | Document-level settings affecting behavior such as mutability, deletion, and transferability | +| [Properties](#document-properties) | Definitions and constraints for each field within a document | +| [Indices](#document-indices) | Definitions for indexing document fields to support efficient querying | + +## Document Properties + +The `properties` object defines each field that a document will use. 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. A full explanation of JSON Schema capabilities 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](https://json-schema.org/understanding-json-schema/reference/index.html) documentation. + +### Assigning Position + +Each property in a level must be assigned a unique `position` value, with ordering starting at zero and incrementing with each property. When using nested objects, position counting resets to zero for each level. This structure supports backward compatibility in data contracts by [ensuring consistent ordering](https://github.com/dashpay/platform/pull/1594) for serialization and deserialization processes. + +### Object Properties + +The `object` type cannot be an empty object but must have one or more defined properties. For example, the `body` property shown below is an object containing a single string property (`objectProperty`): + +```javascript +const contractDocuments = { + message: { + type: "object", + properties: { + body: { + type: "object", + position: 0, + properties: { + objectProperty: { + type: "string", + "position": 0 + }, + }, + additionalProperties: false, + }, + header: { + type: "string", + "position": 1 + } + }, + additionalProperties: false + } +}; +``` + +### Required Properties + +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. Exclude the `required` object for documents without required properties. + +```json +"required": [ + "", + "" +] +``` + +**Example** +The following example (excerpt from the DPNS contract's `domain` document) demonstrates a document with required fields: + +```json +"required": [ + "$createdAt", + "$updatedAt", + "$transferredAt", + "label", + "normalizedLabel", + "normalizedParentDomainName", + "preorderSalt", + "records", + "subdomainRules" +] +``` + +### Transient Properties + +Each document may have transient fields that require validation but do not need to be stored by the system once validated. Transient fields are defined in the `transient` array. Only include the `transient` object for documents with at least one transient property. + +**Example** + +The following example (from the [DPNS contract's `domain` document](https://github.com/dashpay/platform/blob/master/packages/dpns-contract/schema/v1/dpns-contract-documents.json)) demonstrates a document that has 1 transient field: + +```json + "transient": [ + "preorderSalt" + ] +``` + +### Property Constraints + +There are a variety of constraints currently defined for performance and security reasons. + +| Description | Value | +| ----------- | ----- | +| Minimum number of properties | [1](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L22) | +| Maximum number of properties | [100](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L23) | +| Minimum property name length | [1](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L20) | +| Maximum property name length | [64](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L20) | +| Property name characters | Alphanumeric (`A-Z`, `a-z`, `0-9`)
Hyphen (`-`)
Underscore (`_`) | + +## Document Indices + +Document indices may be defined if indexing on document fields is required. The `indices` object should only be included for documents with at least one index. + +The `indices` array consists of one or more objects that each contain: + +* A unique `name` for the index +* A `properties` array composed of a `` object for each document field that is part of the index + + :::{admonition} Compound Indices + :class: attention + When defining an index with multiple properties, the ordering of properties is important. Refer to the [mongoDB documentation](https://docs.mongodb.com/manual/core/index-compound/#prefixes) for details. Dash uses [GroveDB](https://github.com/dashpay/grovedb), which works similarly but requires listing all the index's fields in query order by statements. + ::: +* An optional `unique` element that determines if duplicate values are allowed for the document +* An optional `nullSearchable` element that indicates whether the index allows searching for NULL values. If nullSearchable is false (default: true) and all properties of the index are null then no reference is added. +* An optional `contested` element that determines if duplicate values are allowed for the document + +```json +"indices": [ + { + "name": "", + "properties": [ + { "": "" }, + { "": "" } + ], + "unique": true|false, + "nullSearchable": true|false, + "contested": { + "fieldMatches": [ + { + "field": "", + "regexPattern": "" + } + ], + "resolution": 0 + } + }, + { + "name": "", + "properties": [ + { "": "" }, + ], + } +] +``` + +### Contested Indices + +Contested unique indices provide a way for multiple identities to compete for ownership when a new document field matches a predefined pattern. This system enables fair distribution of valuable documents, such as [premium DPNS names](../explanations/dpns.md#conflict-resolution), through community-driven decision-making. + +A two week contest begins when a match occurs. For the first week, additional contenders can join by paying a fee of 0.2 Dash. During this period, masternodes and evonodes vote on the outcome. The contest can result in the awarding of the document to the winner, a locked vote where no document is awarded, or potentially a restart of the contest if specific conditions are met. + +The table below describes the properties used to configure a contested index: + +| Property Name | Type | Description | +|-|-|-| +| fieldMatches | array | Array containing conditions to check | +| fieldMatches.field | string | Name of the field to check for matches | +| fieldMatches.regexPattern | string | Regex used to check for matches | +| resolution | integer | Method to resolve the contest:
`0` - masternode voting | + +**Example** + +This example (from the [DPNS contract's `domain` document](https://github.com/dashpay/platform/blob/master/packages/dpns-contract/schema/v1/dpns-contract-documents.json)) demonstrates the use of a contested index: + +``` json +"contested": { + "fieldMatches": [ + { + "field": "normalizedLabel", + "regexPattern": "^[a-zA-Z01-]{3,19}$" + } + ], + "resolution": 0, + "description": "If the normalized label part of this index is less than 20 characters (all alphabet a-z, A-Z, 0, 1, and -) then a masternode vote contest takes place to give out the name" +} +``` + +### Index Constraints + +For performance and security reasons, indices have the following constraints. These constraints are subject to change over time. + +| Description | Value | +| ----------- | ----- | +| Minimum/maximum length of index `name` | [1](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L311) / [32](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L312) | +| Maximum number of indices | [10](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L390) | +| Maximum number of unique indices | [10](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v2.rs#L26) | +| Maximum number of contested indices | [1](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v2.rs#L26) | +| Maximum number of properties in a single index | [10](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L331) | +| Maximum length of indexed string property | [63](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs#L72) | +| Usage of `$id` in an index [disallowed](https://github.com/dashpay/platform/pull/178) | N/A | +| **Note: Dash Platform [does not allow indices for arrays](https://github.com/dashpay/platform/pull/225).**
Maximum length of indexed byte array property | [255](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs#L73) | +| **Note: Dash Platform [does not allow indices for arrays](https://github.com/dashpay/platform/pull/225).**
Maximum number of indexed array items | [1024](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs#L74) | + +**Example** +The following example (excerpt from the DPNS contract's `preorder` document) creates an index named `saltedHash` on the `saltedDomainHash` property that also enforces uniqueness across all documents of that type: + +```json +"indices": [ + { + "name": "saltedHash", + "properties": [ + { + "saltedDomainHash": "asc" + } + ], + "unique": true + } +] +``` + +## Document Configuration + +Documents support the following configuration options to provide flexibility in contract design. Only include configuration options in a data contract when using non-default values. + +| Document option | Type | Description | +|-----------------|------|-------------| +| `documentsKeepHistory` | boolean | If true, documents keep a history of all changes. Default: false. | +| `documentsMutable` | boolean | If true, documents are mutable. Default: true. | +| `canBeDeleted` | boolean | If true, documents can be deleted. Default: true. | +| `transferable` | integer | Transferable without a marketplace sell:
`0` - Never
`1` - Always
See the [NFT page](../explanations/nft.md#transfer-and-trade) for more details | +| `tradeMode` | integer | Built-in marketplace system:
`0` - None
`1` - Direct purchase (the purchaser can buy the item without requiring approval)
See the [NFT page](../explanations/nft.md#transfer-and-trade) for more details | +| `creationRestrictionMode` | integer | Restriction of document creation:
`0` - No restrictions
`1` - Contract owner only
`2` - No creation (System Only)
See the [NFT page](../explanations/nft.md#creation-restrictions) for more details | + +| Security option | Type | Description | +|-----------------|------|-------------| +| [`requiresIdentity`
`EncryptionBoundedKey`](./data-contract.md#key-management) | integer | Key requirements for identity encryption:
`0` - Unique non-replaceable
`1` - Multiple
`2` - Multiple with reference to latest key | +| [`requiresIdentity`
`DecryptionBoundedKey`](./data-contract.md#key-management) | integer | Key requirements for identity decryption:
`0` - Unique non-replaceable
`1` - Multiple
`2` - Multiple with reference to latest key | +| `signatureSecurity`
`LevelRequirement` | integer | Public key security level:
`1` - Critical
`2` - High
`3` - Medium. Default is High if none specified. | + +:::{dropdown} List of all usable document properties + + This list of properties is defined in the [Rust DPP implementation](https://github.com/dashpay/platform/blob/master/packages/rs-dpp/src/data_contract/document_type/mod.rs#L31) and the [document meta-schema](https://github.com/dashpay/platform/blob/master/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json). + + | Property Name | Type | Description | + |---------------|------|-------------| + | `type` | string | Specifies the type of the document, constrained to "object". | + | `$schema` | string | The schema URL reference for the document. | + | `$defs` | object | References the `documentProperties` definition. | + | [`indices`](#document-indices) | array | Defines indices for the document with properties like `name`, `unique`, `nullSearchable`, and `contested`. | + | `signatureSecurity`
`LevelRequirement` | integer | Public key security level:
`1` - Critical
`2` - High
`3` - Medium. Default is High if none specified. | + | `documentsKeepHistory` | boolean | If true, documents keep a history of all changes. Default: false. | + | `documentsMutable` | boolean | If true, documents are mutable. Default: true. | + | `canBeDeleted` | boolean | If true, documents can be deleted. Default: true. | + | `transferable` | integer | Transferable without a marketplace sell:
`0` - Never
`1` - Always | + | `tradeMode` | integer | Built-in marketplace system:
`0` - None
`1` - Direct purchase (the purchaser can buy the item without requiring approval) | + | `creationRestrictionMode` | integer | Restriction of document creation:
`0` - No restrictions
`1` - Contract owner only
`2` - No creation (System Only). | + | [`requiresIdentity`
`EncryptionBoundedKey`](./data-contract.md#key-management) | integer | Key requirements for identity encryption:
`0` - Unique non-replaceable
`1` - Multiple
`2` - Multiple with reference to latest key | + | [`requiresIdentity`
`DecryptionBoundedKey`](./data-contract.md#key-management) | integer | Key requirements for identity decryption:
`0` - Unique non-replaceable
`1` - Multiple
`2` - Multiple with reference to latest key | + | [`properties`](#document-properties) | object | Defines the properties of the document. | + | [`transient`](#transient-properties) | array | An array of strings specifying transient properties that are validated by Platform but not stored. | + | [`additionalProperties`](./data-contract.md#additional-properties) | boolean | Specifies whether additional properties are allowed. Must be set to false, meaning no additional properties are allowed beyond those defined. | + +::: + +**Example** + +The following example (from the [DPNS contract's `domain` document](https://github.com/dashpay/platform/blob/master/packages/dpns-contract/schema/v1/dpns-contract-documents.json)) demonstrates the use of several configuration options: + +```json +{ + "domain": { + "documentsMutable": false, + "canBeDeleted": true, + "transferable": 1, + "tradeMode": 1, + "..." + } +} +``` + +## Keyword Constraints + +There are a variety of keyword constraints currently defined for performance and security reasons. The +following constraints apply to document definitions. Unless otherwise noted, these +constraints are defined in the platform's JSON Schema rules (e.g., [rs-dpp document meta +schema](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json)). + +| Keyword | Constraint | +| ------- | ---------- | +| `default` | Restricted - cannot be used (defined in DPP logic) | +| `propertyNames` | Restricted - cannot be used (defined in DPP logic) | +| `uniqueItems: true` | `maxItems` must be defined (maximum: 100000) | +| `pattern: ` | `maxLength` must be defined (maximum: 50000) | +| `format: ` | `maxLength` must be defined (maximum: 50000) | +| `$ref: ` | **Disabled**
`$ref` can only reference `$defs`. Remote references not supported. | +| `if`, `then`, `else`, `allOf`, `anyOf`, `oneOf`, `not` | Disabled for data contracts | +| `dependencies` | Not supported. Use `dependentRequired` and `dependentSchema` instead | +| `additionalItems` | Not supported. Use `items: false` and `prefixItems` instead | +| `patternProperties` | Restricted - cannot be used for data contracts | +| `pattern` | Accept only [RE2](https://github.com/google/re2/wiki/Syntax) compatible regular expressions (defined in DPP logic) | + +## Example Syntax + +This example syntax shows the structure of a documents object that defines two documents, an index, and a required field. + +```json +{ + "": { + "type": "object", + "properties": { + "": { + "type": "", + "position": "" + }, + "": { + "type": "", + "position": "" + }, + }, + "indices": [ + { + "name": "", + "properties": [ + { + "": "asc" + } + ], + "unique": true|false + }, + ], + "required": [ + "" + ], + "additionalProperties": false + }, + "": { + "type": "object", + "properties": { + "": { + "type": "", + "position": "" + }, + "": { + "type": "", + "position": "" + }, + }, + "additionalProperties": false + }, +} +``` + +## Document Schema + +See full document schema details in the [rs-dpp document meta schema](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json). diff --git a/docs/protocol-ref/data-contract.md b/docs/protocol-ref/data-contract.md index d989ab1f8..a581b4921 100644 --- a/docs/protocol-ref/data-contract.md +++ b/docs/protocol-ref/data-contract.md @@ -8,41 +8,25 @@ Data contracts define the schema (structure) of data an application will store on Dash Platform. Contracts are described using [JSON Schema](https://json-schema.org/understanding-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. All data contracts must define one or more [documents](#data-contract-documents), whereas definitions are optional and may not be used for simple contracts. +The following sections provide details that developers need to construct valid contracts. All data contracts must define one or more [documents](#data-contract-documents) or [tokens](#data-contract-tokens), whereas definitions are optional and may not be used for simple contracts. ### General 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. [rs-dpp data contract meta schema](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json)). - -#### Keyword - -| Keyword | Constraint | -| ------- | ---------- | -| `default` | Restricted - cannot be used (defined in DPP logic) | -| `propertyNames` | Restricted - cannot be used (defined in DPP logic) | -| `uniqueItems: true` | `maxItems` must be defined (maximum: 100000) | -| `pattern: ` | `maxLength` must be defined (maximum: 50000) | -| `format: ` | `maxLength` must be defined (maximum: 50000) | -| `$ref: ` | **Disabled**
`$ref` can only reference `$defs` -
remote references not supported | -| `if`, `then`, `else`, `allOf`, `anyOf`, `oneOf`, `not` | Disabled for data contracts | -| `dependencies` | Not supported. Use `dependentRequired` and `dependentSchema` instead | -| `additionalItems` | Not supported. Use `items: false` and `prefixItems` instead | -| `patternProperties` | Restricted - cannot be used for data contracts | -| `pattern` | Accept only [RE2](https://github.com/google/re2/wiki/Syntax) compatible regular expressions (defined in DPP logic) | +There are a variety of constraints currently defined for performance and security reasons. The following constraints are applicable to all aspects of data contracts. #### Data Size | Parameter | Size | | - | - | -| Maximum serialized data contract size | [16384 bytes (16 KB)](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-platform-version/src/version/system_limits/v1.rs#L4) | -| Maximum field value size | [5120 bytes (5 KB)](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-platform-version/src/version/system_limits/v1.rs#L5) | -| Maximum state transition size | [20480 bytes (20 KB)](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-platform-version/src/version/system_limits/v1.rs#L6) | +| Maximum serialized data contract size | [16384 bytes (16 KB)](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-platform-version/src/version/system_limits/v1.rs#L4) | +| Maximum field value size | [5120 bytes (5 KB)](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-platform-version/src/version/system_limits/v1.rs#L5) | +| Maximum state transition size | [20480 bytes (20 KB)](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-platform-version/src/version/system_limits/v1.rs#L6) | A document cannot exceed the maximum state transition size in any case. For example, although it is -possible to define a data contract with 10 fields that each support the maximum field size (5120), -it is not possible to create a document where all 10 fields contain the full 5120 bytes. This is -because the overall document and state transition containing it would be too large (5120 * 10 = -51200 bytes). +possible to define a data contract with 10 document fields that each support the maximum field size +(5120), it is not possible to create a document where all 10 fields contain the full 5120 bytes. +This is because the overall document and state transition containing it would be too large (5120 * +10 = 51200 bytes). #### Additional Properties @@ -56,173 +40,563 @@ Include the following at the same level as the `properties` keyword to ensure pr ## Data Contract Object -The data contract object consists of the following fields as defined in the JavaScript reference client ([rs-dpp](https://github.com/dashpay/platform/blob/v0.24.5/packages/rs-dpp/src/schema/data_contract/dataContractMeta.json)): +The data contract object consists of the following fields as defined in the Rust reference client ([rs-dpp](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/data_contract/v1/data_contract.rs#L46-L75)): + +| Property | Type | Size | Description | +| --------------- | -------------- | ---- | ----------- | +| $version | unsigned integer | 32 bits | The platform protocol version ([currently `8`](https://github.com/dashpay/platform/blob/v1.8.0/packages/rs-platform-version/src/version/mod.rs#L26)) | +| [$schema](#data-contract-schema) | string | Varies | A valid URL | +| [id](#data-contract-id) | array of bytes | 32 bytes | Contract ID generated from `ownerId` and entropy (content media type: `application/x.dash.dpp.identifier`) | +| [version](#data-contract-version) | unsigned integer | Yes | The data contract version | +| ownerId | array of bytes | 32 bytes | [Identity](../protocol-ref/identity.md) that registered the data contract defining the document (content media type: `application/x.dash.dpp.identifier`) | +| [documents](./data-contract-document.md) | object | Varies | (Optional \*) Document definitions (see [Contract Documents](./data-contract-document.md) for details) | +| [config](#data-contract-config) | DataContractConfig | Varies | (Optional) Internal configuration for the contract | +| $defs | object | Varies | (Optional) Definitions for `$ref` references used in the `documents` object (if present, must be a non-empty object with \<= 100 valid properties) | +| [groups](#data-contract-groups) | Group | Varies | (Optional) Groups that allow for specific multiparty actions on the contract. | +| [tokens](./data-contract-token.md) | object | Varies | (Optional \*) Token definitions (see [Contract Tokens](./data-contract-token.md) for details) | -| Property | Type | Required | Description | -| --------------- | -------------- | -------- | ----------- | -| protocolVersion | integer | Yes | The platform protocol version ([currently `7`](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-platform-version/src/version/mod.rs#L25)) | -| $schema | string | Yes | A valid URL (default: ) | -| $id | array of bytes | Yes | Contract ID generated from `ownerId` and entropy ([32 bytes; content media type: `application/x.dash.dpp.identifier`](https://github.com/dashpay/platform/blob/v0.24.5/packages/rs-dpp/src/schema/data_contract/dataContractMeta.json#L378-L384)) | -| version | integer | Yes | The data contract version | -| ownerId | array of bytes | Yes | [Identity](../protocol-ref/identity.md) that registered the data contract defining the document ([32 bytes; content media type: `application/x.dash.dpp.identifier`](https://github.com/dashpay/platform/blob/v0.24.5/packages/rs-dpp/src/schema/data_contract/dataContractMeta.json#L389-L395) | -| documents | object | Yes | Document definitions (see [Documents](#data-contract-documents) for details) | -| $defs | object | No | Definitions for `$ref` references used in the `documents` object (if present, must be a non-empty object with \<= 100 valid properties) | +\* The data contract object must define documents or tokens. It may include both documents and tokens. -### Data Contract Schema +### Data Contract schema -Details regarding the data contract object may be found in the [rs-dpp data contract meta schema](https://github.com/dashpay/platform/blob/v0.24.5/packages/rs-dpp/src/schema/data_contract/dataContractMeta.json). A truncated version is shown below for reference: +The full schema is [defined is rs-dpp](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/data_contract/document_type/schema/enrich_with_base_schema/v0/mod.rs#L6-L7), hosted on [GitHub](https://github.com/dashpay/platform/blob/master/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json), and can be viewed by expanding this dropdown: + +::: {dropdown} Full schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://schema.dash.org/dpp-0-4-0/meta/data-contract", + "$id": "https://github.com/dashpay/platform/blob/master/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json", "type": "object", "$defs": { - // Truncated ... + "documentProperties": { + "type": "object", + "patternProperties": { + "^[a-zA-Z0-9-_]{1,64}$": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/documentSchema" + } + ], + "unevaluatedProperties": false + } + }, + "propertyNames": { + "pattern": "^[a-zA-Z0-9-_]{1,64}$" + }, + "minProperties": 1, + "maxProperties": 100 + }, + "documentSchemaArray": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/documentSchema" + } + ], + "unevaluatedProperties": false + } + }, + "documentSchema": { + "type": "object", + "properties": { + "$id": { + "type": "string", + "pattern": "^#", + "minLength": 1 + }, + "$ref": { + "type": "string", + "pattern": "^#", + "minLength": 1 + }, + "$comment": { + "$ref": "https://json-schema.org/draft/2020-12/meta/core#/properties/$comment" + }, + "description": { + "$ref": "https://json-schema.org/draft/2020-12/meta/meta-data#/properties/description" + }, + "examples": { + "$ref": "https://json-schema.org/draft/2020-12/meta/meta-data#/properties/examples" + }, + "multipleOf": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/multipleOf" + }, + "maximum": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/maximum" + }, + "exclusiveMaximum": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/exclusiveMaximum" + }, + "minimum": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/minimum" + }, + "exclusiveMinimum": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/exclusiveMinimum" + }, + "maxLength": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/maxLength" + }, + "minLength": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/minLength" + }, + "pattern": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/pattern" + }, + "maxItems": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/maxItems" + }, + "minItems": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/minItems" + }, + "uniqueItems": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/uniqueItems" + }, + "contains": { + "$ref": "https://json-schema.org/draft/2020-12/meta/applicator#/properties/contains" + }, + "maxProperties": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/maxProperties" + }, + "minProperties": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/minProperties" + }, + "required": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/required" + }, + "additionalProperties": { + "type": "boolean", + "const": false + }, + "properties": { + "$ref": "#/$defs/documentProperties" + }, + "dependentRequired": { + "type": "object", + "minProperties": 1, + "additionalProperties": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/$defs/stringArray" + } + }, + "const": true, + "enum": { + "type": "array", + "items": true, + "minItems": 1, + "uniqueItems": true + }, + "type": { + "$ref": "https://json-schema.org/draft/2020-12/meta/validation#/properties/type" + }, + "format": { + "$ref": "https://json-schema.org/draft/2020-12/meta/format-annotation#/properties/format" + }, + "contentMediaType": { + "$ref": "https://json-schema.org/draft/2020-12/meta/content#/properties/contentMediaType" + }, + "byteArray": { + "type": "boolean", + "const": true + }, + "position": { + "type": "integer", + "minimum": 0 + } + }, + "dependentSchemas": { + "byteArray": { + "description": "should be used only with array type", + "properties": { + "type": { + "type": "string", + "const": "array" + } + } + }, + "contentMediaType": { + "if": { + "properties": { + "contentMediaType": { + "const": "application/x.dash.dpp.identifier" + } + } + }, + "then": { + "properties": { + "byteArray": { + "const": true + }, + "minItems": { + "const": 32 + }, + "maxItems": { + "const": 32 + } + }, + "required": [ + "byteArray", + "minItems", + "maxItems" + ] + } + }, + "pattern": { + "description": "prevent slow pattern matching of large strings", + "properties": { + "maxLength": { + "type": "integer", + "minimum": 0, + "maximum": 50000 + } + }, + "required": [ + "maxLength" + ] + }, + "format": { + "description": "prevent slow format validation of large strings", + "properties": { + "maxLength": { + "type": "integer", + "minimum": 0, + "maximum": 50000 + } + }, + "required": [ + "maxLength" + ] + } + }, + "allOf": [ + { + "$comment": "require index for object properties", + "if": { + "properties": { + "type": { + "const": "object" + } + }, + "required": [ + "type" + ] + }, + "then": { + "properties": { + "properties": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "position": true + }, + "required": ["position"] + } + } + } + } + }, + { + "$comment": "allow only byte arrays", + "if": { + "properties": { + "type": { + "const": "array" + } + }, + "required": [ + "type" + ] + }, + "then": { + "properties": { + "byteArray": true + }, + "required": [ + "byteArray" + ] + } + }, + { + "$comment": "all object properties must be defined", + "if": { + "properties": { + "type": { + "const": "object" + } + }, + "not": { + "properties": { + "$ref": true + }, + "required": [ + "$ref" + ] + } + }, + "then": { + "properties": { + "properties": { + "$ref": "#/$defs/documentProperties" + }, + "additionalProperties": { + "$ref": "#/$defs/documentSchema/properties/additionalProperties" + } + }, + "required": [ + "properties", + "additionalProperties" + ] + } + } + ] + } }, "properties": { - "protocolVersion": { - "type": "integer", - "minimum": 0, - "$comment": "Maximum is the latest protocol version" + "type": { + "type": "string", + "const": "object" }, "$schema": { "type": "string", - "const": "https://schema.dash.org/dpp-0-4-0/meta/data-contract" - }, - "$id": { - "type": "array", - "byteArray": true, - "minItems": 32, - "maxItems": 32, - "contentMediaType": "application/x.dash.dpp.identifier" + "const": "https://github.com/dashpay/platform/blob/master/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json" }, - "version": { - "type": "integer", - "minimum": 1 + "$defs": { + "$ref": "#/$defs/documentProperties" }, - "ownerId": { + "indices": { "type": "array", - "byteArray": true, - "minItems": 32, - "maxItems": 32, - "contentMediaType": "application/x.dash.dpp.identifier" - }, - "documents": { - "type": "object", - "propertyNames": { - "pattern": "^[a-zA-Z0-9-_]{1,64}$" - }, - "additionalProperties": { + "items": { "type": "object", - "allOf": [ - { + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 32 + }, + "properties": { + "type": "array", + "items": { + "type": "object", + "propertyNames": { + "maxLength": 256 + }, + "additionalProperties": { + "type": "string", + "enum": [ + "asc" + ] + }, + "minProperties": 1, + "maxProperties": 1 + }, + "minItems": 1, + "maxItems": 10 + }, + "unique": { + "type": "boolean" + }, + "nullSearchable": { + "type": "boolean" + }, + "contested": { + "type": "object", "properties": { - "indices": { + "fieldMatches": { "type": "array", "items": { "type": "object", "properties": { - "name": { + "field": { "type": "string", "minLength": 1, - "maxLength": 32 - }, - "properties": { - "type": "array", - "items": { - "type": "object", - "propertyNames": { - "maxLength": 256 - }, - "additionalProperties": { - "type": "string", - "enum": [ - "asc" - ] - }, - "minProperties": 1, - "maxProperties": 1 - }, - "minItems": 1, - "maxItems": 10 + "maxLength": 256 }, - "unique": { - "type": "boolean" + "regexPattern": { + "type": "string", + "minLength": 1, + "maxLength": 256 } }, + "additionalProperties": false, "required": [ - "properties", - "name" - ], - "additionalProperties": false + "field", + "regexPattern" + ] }, - "minItems": 1, - "maxItems": 10 - }, - "type": { - "const": "object" + "minItems": 1 }, - "signatureSecurityLevelRequirement": { + "resolution": { "type": "integer", "enum": [ - 0, - 1, - 2, - 3 + 0 ], - "description": "Public key security level. 0 - Master, 1 - Critical, 2 - High, 3 - Medium. If none specified, High level is used" + "description": "Resolution. 0 - Masternode Vote" + }, + "description": { + "type": "string", + "minLength": 1, + "maxLength": 256 } - } - }, + }, + "required": ["resolution"], + "additionalProperties": false + } + }, + "required": [ + "properties", + "name" + ], + "additionalProperties": false + }, + "minItems": 1, + "maxItems": 10 + }, + "signatureSecurityLevelRequirement": { + "type": "integer", + "enum": [ + 1, + 2, + 3 + ], + "description": "Public key security level. 1 - Critical, 2 - High, 3 - Medium. If none specified, High level is used" + }, + "documentsKeepHistory": { + "type": "boolean", + "description": "True if the documents keep all their history, default is false" + }, + "documentsMutable": { + "type": "boolean", + "description": "True if the documents are mutable, default is true" + }, + "canBeDeleted": { + "type": "boolean", + "description": "True if the documents can be deleted, default is true" + }, + "transferable": { + "type": "integer", + "enum": [ + 0, + 1 + ], + "description": "Transferable without a marketplace sell. 0 - Never, 1 - Always" + }, + "tradeMode": { + "type": "integer", + "enum": [ + 0, + 1 + ], + "description": "Built in marketplace system. 0 - None, 1 - Direct purchase (The user can buy the item without the need for an approval)" + }, + "creationRestrictionMode": { + "type": "integer", + "enum": [ + 0, + 1, + 2 + ], + "description": "Restrictions of document creation. 0 - No restrictions, 1 - Owner only, 2 - No creation (System Only)" + }, + "requiresIdentityEncryptionBoundedKey": { + "type": "integer", + "enum": [ + 0, + 1, + 2 + ], + "description": "Key requirements. 0 - Unique Non Replaceable, 1 - Multiple, 2 - Multiple with reference to latest key." + }, + "requiresIdentityDecryptionBoundedKey": { + "type": "integer", + "enum": [ + 0, + 1, + 2 + ], + "description": "Key requirements. 0 - Unique Non Replaceable, 1 - Multiple, 2 - Multiple with reference to latest key." + }, + "properties": { + "type": "object", + "additionalProperties": { + "type": "object", + "allOf": [ { "$ref": "#/$defs/documentSchema" } ], "unevaluatedProperties": false }, + "properties": { + "$id": true, + "$ownerId": true, + "$revision": true, + "$createdAt": true, + "$updatedAt": true, + "$transferredAt": true, + "$createdAtBlockHeight": true, + "$updatedAtBlockHeight": true, + "$transferredAtBlockHeight": true, + "$createdAtCoreBlockHeight": true, + "$updatedAtCoreBlockHeight": true, + "$transferredAtCoreBlockHeight": true + }, + "propertyNames": { + "oneOf": [ + { + "type": "string", + "pattern": "^[a-zA-Z0-9-_]{1,64}$" + }, + { + "type": "string", + "enum": [ + "$id", + "$ownerId", + "$revision", + "$createdAt", + "$updatedAt", + "$transferredAt", + "$createdAtBlockHeight", + "$updatedAtBlockHeight", + "$transferredAtBlockHeight", + "$createdAtCoreBlockHeight", + "$updatedAtCoreBlockHeight", + "$transferredAtCoreBlockHeight" + ] + } + ] + }, "minProperties": 1, "maxProperties": 100 }, - "$defs": { - "$ref": "#/$defs/documentProperties" + "transient": { + "type": "array", + "items": { + "type": "string" + } + }, + "additionalProperties": { + "type": "boolean", + "const": false } }, "required": [ - "protocolVersion", "$schema", - "$id", - "version", - "ownerId", - "documents" - ], - "additionalProperties": false + "type", + "properties", + "additionalProperties" + ] } ``` -**Example** - -```json -{ - "id": "AoDzJxWSb1gUi2dSmvFeUFpSsjZQRJaqCpn7vCLkwwJj", - "ownerId": "7NUbPf231ixt1kVBQsBvSMMBxd7AgPad8KtdtfFGhXDP", - "schema": "https://schema.dash.org/dpp-0-4-0/meta/data-contract", - "documents": { - "note": { - "properties": { - "message": { - "type": "string" - } - }, - "additionalProperties": false - } - } -} -``` +::: ### Data Contract id -The data contract `$id` is a hash of the `ownerId` and entropy as shown [here](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/src/data_contract/generate_data_contract.rs). +The data contract `id` is a hash of the `ownerId` and entropy as shown [here](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/data_contract/generate_data_contract.rs). ```rust // From the Rust reference implementation (rs-dpp) @@ -244,317 +618,94 @@ pub fn generate_data_contract_id_v0( The data contract `version` is an integer representing the current version of the contract. This property must be incremented if the contract is updated. -### Data Contract Documents +### Data Contract 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](#document-indices) and a list of [required properties](#required-properties-optional). The `additionalProperties` properties keyword must be included as described in the [constraints](#additional-properties) section. +See the [data contract documents](./data-contract-document.md) page for details. -The following example shows a minimal `documents` object defining a single document (`note`) that has one property (`message`). +### Data Contract config -```json -{ - "note": { - "type": "object", - "properties": { - "message": { - "type": "string", - "position": 0 - } - }, - "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. - -**Note:** The `object` type is required to have properties defined. For example, the body property shown below is an object containing a single string property (objectProperty): - -```javascript -const contractDocuments = { - message: { - "type": "object", - properties: { - body: { - type: "object", - properties: { - objectProperty: { - type: "string", - position: 0 - }, - }, - additionalProperties: false, - }, - header: { - type: "string", - position: 1 - } - }, - additionalProperties: false - } -}; -``` - -**Note:** 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](https://json-schema.org/understanding-json-schema/reference/index.html) documentation. - -##### Property Constraints - -There are a variety of constraints currently defined for performance and security reasons. - -| Description | Value | -| ----------- | ----- | -| Minimum number of properties | [1](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L22) | -| Maximum number of properties | [100](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L23) | -| Minimum property name length | [1](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L20) | -| Maximum property name length | [64](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L20) | -| Property name characters | Alphanumeric (`A-Z`, `a-z`, `0-9`)
Hyphen (`-`)
Underscore (`_`) | +The data contract config defines configuration options for data contracts, controlling their lifecycle, mutability, history management, and encryption requirements. Data contracts support three categories of configuration options to provide flexibility in contract design. It is only necessary to include them in a data contract when non-default values are used. The default values for these configuration options are defined in the [Rust DPP implementation](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/data_contract/config/fields.rs). -##### Required Properties (Optional) +| Contract option | Default | Description | +|-----------------------------------------|---------|-------------| +| `canBeDeleted` | `false` | Determines if the contract can be deleted | +| `readonly` | `false` | Determines if the contract is read-only. Read-only contracts cannot be updated. | +| `keepsHistory` | `false` | Determines if changes to the contract itself are tracked, maintaining a historical record of contract modifications. | -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. +| Document default option | Default | Description | +|-----------------------------------------|---------|-------------| +| `documentsKeepHistory`
`ContractDefault` | `false` | Sets the default behavior for tracking historical changes of documents within the contract | +| `documentsMutable`
`ContractDefault` | `true` | Sets the default mutability of documents within the contract, indicating if documents can be edited. | +| `documentsCanBeDeleted`
`ContractDefault` | `true` | Sets the default behavior for whether documents within the contract can be deleted | -```json -"required": [ - "", - "" -] -``` - -**Example** -The following example (excerpt from the DPNS contract's `domain` document) demonstrates a document that has 6 required fields: +#### Key Management -```json -"required": [ - "label", - "normalizedLabel", - "normalizedParentDomainName", - "preorderSalt", - "records", - "subdomainRules" -] -``` +Dash Platform provides an advanced level of security and control by enabling the isolation of encryption and decryption keys on a contract-specific or document-specific basis. This granular approach to key management enables developers to configure their applications for whatever level of security they require. -#### Document Indices +| Security option | Description | +|-----------------------------------------|-------------| +| `requiresIdentity`
`EncryptionBoundedKey` | Indicates the contract requires a contract-specific identity encryption key. Key options:
`0` - Unique non-replaceable
`1` - Multiple
`2` - Multiple with reference to latest | +| `requiresIdentity`
`DecryptionBoundedKey` | Indicates the contract requires a contract-specific identity decryption key. Key options:
`0` - Unique non-replaceable
`1` - Multiple
`2` - Multiple with reference to latest | -Document indices may be defined if indexing on document fields is required. +:::{tip} +These security options can be set at the root level of the data contract or the root level of specific documents within the contract depending on requirements. +::: -The `indices` array consists of: - -- One or more objects that each contain: - - A unique `name` for the index - - A `properties` array composed of a `` 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 type - -**Note:** +**Example** -- The `indices` object should be excluded for documents that do not require 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](https://docs.mongodb.com/manual/core/index-compound/#prefixes) for details regarding the significance of the order as it relates to querying capabilities. Dash uses [GroveDB](https://github.com/dashpay/grovedb) which works similarly but does requiring listing _all_ the index's fields in query order by statements. +The following example (from the [DashPay contract's `contactRequest` document](https://github.com/dashpay/platform/blob/master/packages/dashpay-contract/schema/v1/dashpay.schema.json#L142-L146)) demonstrates the use of both key-related options at the document level: -```json -"indices": [ - { - "name": "Index1", - "properties": [ - { "": "asc" }, - { "": "asc" } - ], - "unique": true|false - }, - { - "name": "Index2", - "properties": [ - { "": "asc" }, - ], - } -] +``` json +"contactRequest": { + "requiresIdentityEncryptionBoundedKey": 2, + "requiresIdentityDecryptionBoundedKey": 2, +} ``` -##### Index Constraints - -For performance and security reasons, indices have the following constraints. These constraints are subject to change over time. +See the data contract [config implementation in rs-dpp](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/data_contract/config/v0/mod.rs#L17-L42) for more details. -| Description | Value | -| ----------- | ----- | -| Minimum/maximum length of index `name` | [1](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L311) / [32](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L312) | -| Maximum number of indices | [10](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L390) | -| Maximum number of unique indices | [10](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v2.rs#L24) | -| Maximum number of properties in a single index | [10](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json#L331) | -| Maximum length of indexed string property | [63](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs#L72) | -| Maximum number of contested indices | [1](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v2.rs#L22) | -| Usage of `$id` in an index [disallowed](https://github.com/dashpay/platform/pull/178) | N/A | -| **Note: Dash Platform v0.22+ [does not allow indices for arrays](https://github.com/dashpay/platform/pull/225).**
Maximum length of indexed byte array property | [255](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs#L73) | -| **Note: Dash Platform v0.22+ [does not allow indices for arrays](https://github.com/dashpay/platform/pull/225).**
Maximum number of indexed array items | [1024](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs#L74) | +### Data Contract groups -**Example** -The following example (excerpt from the DPNS contract's `preorder` document) creates an index named `saltedHash` on the `saltedDomainHash` property that also enforces uniqueness across all documents of that type: +Groups can be used to distribute contract configuration and update authorization across multiple identities. They are particularly useful for contracts where multiple parties are involved in controlling or managing contract-specific features. Each group defines a set of member identities, the voting power of each member, and the required power threshold to authorize an action. -```json -"indices": [ - { - "name": "saltedHash", - "properties": [ - { - "saltedDomainHash": "asc" - } - ], - "unique": true - } -] -``` +- Each member is assigned an integer power. +- The group itself has a required power threshold to authorize an action. +- Groups can have up to 256 members, each with a maximum power of 2^16 - 1. +- Changes to a token (e.g., mint, burn, freeze) can be configured so they require group authorization. + - Example: "2-of-3 multisig” among three admins, each with certain voting power. -#### Full Document Syntax - -This example syntax shows the structure of a documents object that defines two documents, an index, and a required field. - -```json -{ - "": { - "type": "object", - "properties": { - "": { - "type": "", - "position": "" - }, - "": { - "type": "", - "position": "" - }, - }, - "indices": [ - { - "name": "", - "properties": [ - { - "": "asc" - } - ], - "unique": true|false - }, - ], - "required": [ - "" - ] - "additionalProperties": false - }, - "": { - "type": "object", - "properties": { - "": { - "type": "", - "position": "" - }, - "": { - "type": "", - "position": "" - }, - }, - "additionalProperties": false - }, -} -``` +See the [groups implementation in rs-dpp](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/data_contract/group/v0/mod.rs#L31-L34) for more details. -#### Document Schema +### Data Contract tokens -Full document schema details may be found in the [rs-dpp document meta schema](https://github.com/dashpay/platform/blob/v1.7.1/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json). +- Tokens provide token-related functionality within the contract, such as base supply, maximum supply, and manual minting/burning rules. +- Token configurations include change control rules, ensuring proper governance for modifying supply limits and token-related settings. +- This enables contracts to define and manage tokens while ensuring compliance with governance rules (e.g., who can mint or burn tokens). ## Data Contract State Transition Details -There are two data contract-related state transitions: [data contract create](#data-contract-creation) and [data contract update](#data-contract-update). Details are provided in this section. +There are two data contract-related state transitions: [data contract create](#data-contract-create) and [data contract update](#data-contract-update). Details are provided in this section. -### Data Contract Creation +### Data Contract Create Data contracts are created on the platform by submitting the [data contract object](#data-contract-object) in a data contract create state transition consisting of: -| Field | Type | Description | -| ----- | ---- | ----------- | -| protocolVersion | integer | The platform protocol version ([currently `1`](https://github.com/dashpay/platform/blob/v0.24.5/packages/rs-dpp/src/version/mod.rs#L9)) | -| type | integer | State transition type (`0` for data contract create) | -| dataContract | [data contract object](#data-contract-object) | Object containing the data contract details | -| entropy | array of bytes | Entropy used to generate the data contract ID. Generated as [shown here](../protocol-ref/state-transition.md#entropy-generation). (32 bytes) | -| signaturePublicKeyId | number | The `id` of the [identity public key](../protocol-ref/identity.md#identity-publickeys) that signed the state transition | -| signature | array of bytes | Signature of state transition data (65 or 96 bytes) | - -Each data contract state transition must comply with this JSON-Schema definition established in [rs-dpp](https://github.com/dashpay/platform/blob/v0.24.5/packages/rs-dpp/src/schema/data_contract/stateTransition/dataContractCreate.json): - -```json -{ - "$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": 0 - }, - "dataContract": { - "type": "object" - }, - "entropy": { - "type": "array", - "byteArray": true, - "minItems": 32, - "maxItems": 32 - }, - "signaturePublicKeyId": { - "type": "integer", - "minimum": 0 - }, - "signature": { - "type": "array", - "byteArray": true, - "minItems": 65, - "maxItems": 96 - } - }, - "additionalProperties": false, - "required": [ - "protocolVersion", - "type", - "dataContract", - "entropy", - "signaturePublicKeyId", - "signature" - ] -} -``` +| Field | Type | Size | Description | +| --------------- | -------------- | ---- | ----------- | +| $version | unsigned integer | 32 bits | The platform protocol version (currently `1`) | +| type | unsigned integer | 8 bits | State transition type (`0` for data contract create) | +| dataContract | [data contract object](#data-contract-object) | Varies | Object containing the data contract details | +| identityNonce | unsigned integer | 64 bits | Identity nonce for this transition to prevent replay attacks | +| entropy | array of bytes | 32 bytes | Entropy used to generate the data contract ID. Generated as [shown here](../protocol-ref/state-transition.md#entropy-generation). | +| userFeeIncrease | unsigned integer | 16 bits | Extra fee to prioritize processing if the mempool is full. Typically set to zero. | +| signaturePublicKeyId | unsigned integer | 32 bits | The `id` of the [identity public key](../protocol-ref/identity.md#identity-publickeys) that signed the state transition (`=> 0`) | +| signature | array of bytes | 65 bytes | Signature of state transition data | -**Example State Transition** - -```json -{ - "protocolVersion":1, - "type":0, - "signature":"IFmEb/OwyYG0yn33U4/kieH4JL63Ft25GAun+XqWOalkbDrpL9z+OH+Sb03xsyMNzoILC2T1Q8yV1q7kCmr0HuQ=", - "signaturePublicKeyId":0, - "dataContract":{ - "protocolVersion":1, - "$id":"44dvUnSdVtvPPeVy6mS4vRzJ4zfABCt33VvqTWMM8VG6", - "$schema":"https://schema.dash.org/dpp-0-4-0/meta/data-contract", - "version":1, - "ownerId":"6YfP6tT9AK8HPVXMK7CQrhpc8VMg7frjEnXinSPvUmZC", - "documents":{ - "note":{ - "type":"object", - "properties":{ - "message":{ - "type":"string" - } - }, - "additionalProperties":false - } - } - }, - "entropy":"J2Sl/Ka9T1paYUv6f2ec5MzaaACs9lcUvOskBU0SMlo=" -} -``` +See the [data contract create implementation in rs-dpp](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/v0/mod.rs#L37-L45) for more details. ### Data Contract Update -Existing data contracts can be updated in certain backwards-compatible ways. The following aspects +Existing data contracts can be updated in certain backwards-compatible ways. The following aspects of a data contract can be updated: - Adding a new document @@ -564,94 +715,24 @@ of a data contract can be updated: Data contracts are updated on the platform by submitting the modified [data contract object](#data-contract-object) in a data contract update state transition consisting of: -| Field | Type | Description | -| -------------------- | -------------- | ----------- | -| protocolVersion | integer | The platform protocol version ([currently `1`](https://github.com/dashpay/platform/blob/v0.24.5/packages/rs-dpp/src/version/mod.rs#L9)) | -| type | integer | State transition type (`4` for data contract update) | -| dataContract | [data contract object](#data-contract-object) | Object containing the updated data contract details
**Note:** the data contract's [`version` property](#data-contract-version) must be incremented with each update | -| signaturePublicKeyId | number | The `id` of the [identity public key](../protocol-ref/identity.md#identity-publickeys) that signed the state transition | -| signature | array of bytes | Signature of state transition data (65 or 96 bytes) | +| Field | Type | Size | Description | +| --------------- | -------------- | ---- | ----------- | +| $version | unsigned integer | 32 bits | The platform protocol version (currently `1`) | +| type | unsigned integer | 8 bits | State transition type (`4` for data contract update) | +| dataContract | [data contract object](#data-contract-object) | Varies | Object containing the updated data contract details
**Note:** the data contract's [`version` property](#data-contract-version) must be incremented with each update | +| signaturePublicKeyId | unsigned integer | 32 bits | The `id` of the [identity public key](../protocol-ref/identity.md#identity-publickeys) that signed the state transition (`=> 0`) | +| signature | array of bytes | 65 bytes | Signature of state transition data | -Each data contract state transition must comply with this JSON-Schema definition established in -[rs-dpp](https://github.com/dashpay/platform/blob/v0.24.5/packages/rs-dpp/src/schema/data_contract/stateTransition/dataContractUpdate.json): - -```json -{ - "$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": 4 - }, - "dataContract": { - "type": "object" - }, - "signaturePublicKeyId": { - "type": "integer", - "minimum": 0 - }, - "signature": { - "type": "array", - "byteArray": true, - "minItems": 65, - "maxItems": 96 - } - }, - "additionalProperties": false, - "required": [ - "protocolVersion", - "type", - "dataContract", - "signaturePublicKeyId", - "signature" - ] -} -``` - -**Example State Transition** - -```json -{ - "protocolVersion":1, - "type":4, - "signature":"IBboAbqbGBiWzyJDyhwzs1GujR6Gb4m5Gt/QCugLV2EYcsBaQKTM/Stq7iyIm2YyqkV8VlWqOfGebW2w5Pjnfak=", - "signaturePublicKeyId":0, - "dataContract":{ - "protocolVersion":1, - "$id":"44dvUnSdVtvPPeVy6mS4vRzJ4zfABCt33VvqTWMM8VG6", - "$schema":"https://schema.dash.org/dpp-0-4-0/meta/data-contract", - "version":2, - "ownerId":"6YfP6tT9AK8HPVXMK7CQrhpc8VMg7frjEnXinSPvUmZC", - "documents":{ - "note":{ - "type":"object", - "properties":{ - "message":{ - "type":"string" - }, - "author":{ - "type":"string" - } - }, - "additionalProperties":false - } - } - } -} -``` +See the [data contract update implementation in rs-dpp](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_update_transition/v0/mod.rs#L33-L45) for more details. ### Data Contract State Transition Signing -Data contract state transitions must be signed by a private key associated with the contract owner's identity. +Data contract state transitions must be signed by a private key associated with the contract owner's identity. See the [state transition signing](./state-transition.md#state-transition-signing) page for full signing details. -The process to sign a data contract state transition consists of the following steps: +```{toctree} +:maxdepth: 2 +:titlesonly: +:hidden: -1. Canonical CBOR encode the state transition data - this include all ST fields except the `signature` and `signaturePublicKeyId` -2. Sign the encoded data with a private key associated with the `ownerId` -3. Set the state transition `signature` to the value of the signature created in the previous step -4. Set the state transition`signaturePublicKeyId` to the [public key `id`](../protocol-ref/identity.md#public-key-id) corresponding to the key used to sign +data-contract-document +``` diff --git a/docs/protocol-ref/overview.md b/docs/protocol-ref/overview.md index 388904310..632df74fb 100644 --- a/docs/protocol-ref/overview.md +++ b/docs/protocol-ref/overview.md @@ -6,7 +6,7 @@ ## Introduction -The Dash Platform Protocol (DPP) defines a protocol for the data objects (e.g. [identities](../protocol-ref/identity.md), data contracts, documents, state transitions) that can be stored on [Dash's layer 2 platform](../intro/what-is-dash-platform.md). All data stored on Dash Platform is governed by DPP to ensure data consistency and integrity is maintained. +The Dash Platform Protocol (DPP) defines a protocol for the data objects (e.g., [identities](../protocol-ref/identity.md), data contracts, documents, state transitions) that can be stored on [Dash's layer 2 platform](../intro/what-is-dash-platform.md). All data stored on Dash Platform is governed by DPP to ensure data consistency and integrity is maintained. Dash Platform data objects consist of JSON and are validated using the JSON Schema specification via pre-defined JSON Schemas and meta-schemas described in these sections. The meta-schemas allow for creation of DPP-compliant schemas which define fields for third-party Dash Platform applications. diff --git a/docs/protocol-ref/state-transition.md b/docs/protocol-ref/state-transition.md index 9d4bdbb63..7316b25a8 100644 --- a/docs/protocol-ref/state-transition.md +++ b/docs/protocol-ref/state-transition.md @@ -9,7 +9,7 @@ State transitions are the means for submitting data that creates, updates, or deletes platform data and results in a change to a new state. Each one must contain: - [Common fields](#common-fields) present in all state transitions -- Additional fields specific to the type of action the state transition provides (e.g. [creating an identity](../protocol-ref/identity.md#identity-create)) +- Additional fields specific to the type of action the state transition provides (e.g., [creating an identity](../protocol-ref/identity.md#identity-create)) ### Fees @@ -26,7 +26,7 @@ The list of common fields used by multiple state transitions is defined in [rs-d | Field | Type | Size | Description | | --------------- | -------------- | ---- | ----------- | | $version | unsigned integer | 32 bits | The platform protocol version (currently `1`) | -| type | unsigned integer | 8 bits | State transition type:
`0` - [data contract create](../protocol-ref/data-contract.md#data-contract-creation)
`1` - [batch](#batch)
`2` - [identity create](../protocol-ref/identity.md#identity-create)
`3` - [identity topup](identity.md#identity-topup)
`4` - [data contract update](data-contract.md#data-contract-update)
`5` - [identity update](identity.md#identity-update)
`6` - [identity credit transfer](identity.md#identity-credit-transfer)
`7` - [identity credit withdrawal](identity.md#identity-credit-withdrawal)
`8` - [masternode vote](#masternode-vote) | +| type | unsigned integer | 8 bits | State transition type:
`0` - [data contract create](../protocol-ref/data-contract.md#data-contract-create)
`1` - [batch](#batch)
`2` - [identity create](../protocol-ref/identity.md#identity-create)
`3` - [identity topup](identity.md#identity-topup)
`4` - [data contract update](data-contract.md#data-contract-update)
`5` - [identity update](identity.md#identity-update)
`6` - [identity credit transfer](identity.md#identity-credit-transfer)
`7` - [identity credit withdrawal](identity.md#identity-credit-withdrawal)
`8` - [masternode vote](#masternode-vote) | | userFeeIncrease | unsigned integer | 16 bits | Extra fee to prioritize processing if the mempool is full. Typically set to zero. | | signature | array of bytes | 65 bytes |Signature of state transition data | @@ -60,7 +60,7 @@ More detailed information about the `dataContract` object can be found in the [d #### Entropy Generation -Entropy is included in [Data Contracts](../protocol-ref/data-contract.md#data-contract-creation) and [Documents](../protocol-ref/document.md#document-create-transition). Dash Platform using the following entropy generator found in [rs-dpp](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/util/entropy_generator.rs#L12-L16): +Entropy is included in [Data Contracts](../protocol-ref/data-contract.md#data-contract-create) and [Documents](../protocol-ref/document.md#document-create-transition). Dash Platform using the following entropy generator found in [rs-dpp](https://github.com/dashpay/platform/blob/v2.0-dev/packages/rs-dpp/src/util/entropy_generator.rs#L12-L16): ```rust // From the Rust reference implementation (rs-dpp)