diff --git a/CLAUDE.md b/CLAUDE.md index 8cc4a1371..9760866d1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -74,6 +74,14 @@ When updating documentation values that include GitHub source links: - Update the line anchor (`#L`) to match the correct line **in the branch the link points to** - When available, use the local platform repository checkout to verify line numbers against the correct branch +## Adding a new doc page + +A new page is only visible in the rendered site if it appears in a Sphinx toctree. Sphinx will emit a `document isn't included in any toctree` warning at build time for any orphaned page, and the page won't show up in the sidebar. + +Top-level toctrees live in [docs/index.md](docs/index.md), grouped by section caption (`Tutorials`, `Explanations`, `Reference`, `Platform Protocol Reference`, `Resources`). When you add a new page under `docs/
/`, add its path (without the `.md` extension) to the matching toctree in `docs/index.md`. After editing the toctree, run `python scripts/sync_sidebar.py` so the custom sidebar template picks up the new entry. + +Tutorials and the TUI section use nested `index.md` files with their own toctrees — check the parent `index.md` of the directory you're adding to. + ## DAPI endpoint reference The DAPI endpoint reference is split between an overview page (`docs/reference/dapi-endpoints.md`) and per-section detail pages (`docs/reference/dapi-endpoints-*.md`). The authoritative list of endpoints lives in the platform proto at `https://github.com/dashpay/platform/tree//packages/dapi-grpc/protos` — check the proto when adding or modifying entries. diff --git a/_templates/sidebar-main.html b/_templates/sidebar-main.html index 56fa79b72..c973bc7b4 100644 --- a/_templates/sidebar-main.html +++ b/_templates/sidebar-main.html @@ -335,6 +335,11 @@ DashPay +
  • + + Shielded Pool + +
  • Fees @@ -484,6 +489,11 @@ Platform Address System
  • +
  • + + Shielded Pool + +
  • Protocol Constants diff --git a/docs/explanations/shielded-pool.md b/docs/explanations/shielded-pool.md new file mode 100644 index 000000000..489ec95dc --- /dev/null +++ b/docs/explanations/shielded-pool.md @@ -0,0 +1,73 @@ +```{eval-rst} +.. _explanations-shielded-pool: +``` + +# Shielded Pool + +## Overview + +The shielded pool is an optional privacy layer on Dash Platform that lets users hold and move credits without revealing balances, sender, or recipient on-chain. Funds move *into* the pool through a shield transition, move *within* the pool privately, and exit through an unshield or shielded withdrawal. While funds remain inside the pool, only their owner can see them. + +The pool uses the [Orchard](https://zips.z.cash/protocol/protocol.pdf) shielded protocol — the same zk-SNARK-based design used by Zcash for its current shielded pool. Transactions inside the pool prove their own validity without disclosing the amounts or parties involved. + +## When to use the shielded pool + +Shielded transitions cost more than transparent ones — they carry a zero-knowledge proof and produce permanent on-chain artifacts (note commitments, nullifiers, and encrypted note ciphertexts). Use the pool when you need confidentiality for a specific payment, transfer, or balance. Use transparent transitions for everyday activity where privacy is not a requirement. + +The pool is well-suited to: + +- Payments where the amount or counterparty should not be public. +- Holding balances privately before unshielding to spend transparently. +- Moving credits between identities or addresses you control without linking them. + +## Core concepts + +### Notes, commitments, and the note tree + +Each unit of value in the pool is held as a **note** — an off-chain record describing an owner, an amount, and a unique randomness value. When a note is created, the platform records only its **commitment** (a hash of the note) into an append-only Merkle tree called the **note commitment tree**. The note itself is never published; only its commitment is, and the commitment reveals nothing about the note's contents. + +The root of the note commitment tree is called an **anchor**. Anchors serve as snapshots that shielded transitions reference to prove "the note I am spending was added to the tree by some earlier transition." Spenders prove membership against an anchor without revealing *which* note they are spending. + +### Nullifiers + +When a note is spent, the spender publishes a unique **nullifier** derived from the note. The platform tracks all nullifiers ever published; spending the same note twice would produce the same nullifier and be rejected as a double-spend. + +Nullifiers are unlinkable to their notes' commitments. An observer can see that *some* note was spent but cannot tell which one. This is how the pool prevents double-spends while preserving privacy. + +### Encrypted notes + +When a note is created for a recipient, the platform stores an **encrypted note payload** alongside the commitment. The recipient scans new encrypted notes, attempts trial decryption with their viewing key, and learns about notes addressed to them. Other observers see only opaque ciphertext. + +### Actions and the action-count limit + +A shielded transition is composed of one or more **actions**. Each action structurally pairs one spend (consuming a prior note) with one output (creating a new note), bundled together so observers cannot tell which spend funded which output. A single shielded transition is limited to **16 actions** to keep transitions within the platform's 20 KB state-transition size budget. + +## Transition types + +Five state transition types interact with the shielded pool. The wire-level structure of each — including field-by-field tables and source links — is documented in the [Shielded Pool protocol reference](../protocol-ref/shielded-pool.md). + +### Shield + +Moves credits *into* the pool from one or more [Platform addresses](../protocol-ref/address-system.md#platform-address) the sender controls. The total contributed across address inputs must cover the value being shielded plus the transition fee. Excess credits remain in the source addresses. + +### Shield from asset lock + +Moves credits *into* the pool directly from a Dash Core (L1) asset-lock transaction. This avoids first funding a Platform address and lets users enter the pool in a single Platform transition tied to an L1 lock proof. + +### Shielded transfer + +Moves credits *within* the pool — between notes — without any transparent surface. To an outside observer, only the actions, anchor, proof, and binding signature are visible; the sender, recipient, and amount remain private. + +### Unshield + +Moves credits *out of* the pool to a [Platform address](../protocol-ref/address-system.md#platform-address) the sender designates. The unshielded amount becomes spendable through normal address-based transitions. + +### Shielded withdrawal + +Moves credits *out of* the pool back to Dash Core (L1) via the platform's withdrawal mechanism. Like an unshield, it reveals an amount and an L1 destination, but the funds leave Platform entirely rather than landing in a Platform address. + +## What the pool does not provide + +- **Anonymity sets**: The privacy guarantee depends on how many other notes exist in the pool. A pool with a single user offers limited cover; privacy improves as more users participate. +- **L1 transaction privacy**: Funds entering or leaving the pool traverse transparent transitions or L1 transactions on either side. Only activity *inside* the pool is shielded. +- **Hiding the act of using the pool**: Observers can see that a transition is a shield, unshield, or transfer — they just cannot see who or how much is involved on the shielded side. diff --git a/docs/index.md b/docs/index.md index e89b33b43..e42d5fdf5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -131,6 +131,7 @@ explanations/dpns explanations/drive explanations/platform-consensus explanations/dashpay +explanations/shielded-pool explanations/fees explanations/tokens explanations/nft @@ -164,6 +165,7 @@ protocol-ref/document protocol-ref/token protocol-ref/data-trigger protocol-ref/address-system +protocol-ref/shielded-pool protocol-ref/protocol-constants protocol-ref/errors ``` diff --git a/docs/protocol-ref/protocol-constants.md b/docs/protocol-ref/protocol-constants.md index c06962160..a5a620808 100644 --- a/docs/protocol-ref/protocol-constants.md +++ b/docs/protocol-ref/protocol-constants.md @@ -21,7 +21,7 @@ Maximum sizes and limits for various platform components. | Max withdrawal amount | 50,000,000,000,000 credits | 500 Dash maximum per withdrawal | [rs-platform-version](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/system_limits/v1.rs#L10) | | Max contract group size | 256 | Maximum members per group | [rs-platform-version](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/system_limits/v1.rs#L11) | | Max token redemption cycles | 128 | Maximum redemption cycles | [rs-platform-version](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/system_limits/v1.rs#L12) | -| Max shielded transition actions | 100 | Maximum shielded transitions per batch | [rs-platform-version](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/system_limits/v1.rs#L13) | +| Max shielded transition actions | 16 | Maximum [actions](shielded-pool.md#actions) per shielded transition | [rs-platform-version](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/system_limits/v1.rs#L27) | | Max CBOR encoded length | 16,384 bytes (16 KiB) | Maximum CBOR encoding size | [rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/util/cbor_serializer.rs#L8) | | Contract deserialization limit | 15,000 | Maximum contract deserialization | [rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/data_contract/serialized_version/mod.rs#L38) | @@ -268,6 +268,7 @@ These limits apply to token perpetual distribution function parameters. | Max fee strategies | 4 | Maximum fee strategy steps | [rs-platform-version](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v3.rs#L45) | | Max address inputs | 16 | Maximum input addresses per address-based transition | [rs-platform-version](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v3.rs#L43) | | Max address outputs | 128 | Maximum output addresses per address-based transition | [rs-platform-version](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v3.rs#L44) | +| Max asset lock transaction inputs | 100 | Maximum L1 transaction inputs in an asset lock proof | [rs-platform-version](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v3.rs#L25) | ## Epoch and Time Constants diff --git a/docs/protocol-ref/shielded-pool.md b/docs/protocol-ref/shielded-pool.md new file mode 100644 index 000000000..6279b9de5 --- /dev/null +++ b/docs/protocol-ref/shielded-pool.md @@ -0,0 +1,213 @@ +```{eval-rst} +.. _protocol-ref-shielded-pool: +``` + +# Shielded Pool + +:::{attention} +Shielded state transitions were [enabled in Protocol Version 12](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-platform-version/src/version/feature_initial_protocol_versions.rs#L4). They use the [Orchard](https://zips.z.cash/protocol/protocol.pdf) shielded protocol to move credits into, within, and out of a pool that hides amounts, senders, and recipients. + +For the conceptual overview of how the pool works and when to use it, see [Shielded Pool](../explanations/shielded-pool.md). +::: + +## Overview + +The shielded pool is implemented through five state transition types that share a common Orchard bundle structure: + +| Type | Name | Description | +| --- | --- | --- | +| 15 | [Shield](#shield) | Move credits from Platform addresses into the shielded pool | +| 16 | [Shielded Transfer](#shielded-transfer) | Move credits within the pool (no transparent surface) | +| 17 | [Unshield](#unshield) | Move credits from the pool to a Platform address | +| 18 | [Shield from Asset Lock](#shield-from-asset-lock) | Move credits from an L1 asset lock directly into the pool | +| 19 | [Shielded Withdrawal](#shielded-withdrawal) | Move credits from the pool back to Dash Core (L1) | + +All five transitions share a common Orchard bundle (anchor, actions, proof, binding signature). Transitions that touch the transparent side (Shield, Unshield, Shield from Asset Lock, Shielded Withdrawal) layer the transparent fields on top of that bundle. Shielded Transfer has no transparent surface beyond the bundle itself. + +## Common Components + +### Orchard Bundle + +Every shielded transition includes an Orchard bundle proving that a set of note spends and outputs is internally consistent. The bundle consists of: + +| Field | Type | Size | Description | +| --- | --- | --- | --- | +| actions | array | Varies | Orchard [actions](#actions) (spend-output pairs). Limited to [`max_shielded_transition_actions`](protocol-constants.md) per transition. | +| anchor | array of bytes | 32 bytes | Sinsemilla root of the note commitment tree at bundle creation time. Must match an [anchor](#anchors) the platform has previously recorded | +| proof | array of bytes | Varies | Halo 2 zero-knowledge proof that the actions are valid | +| bindingSignature | array of bytes | 64 bytes | RedPallas signature binding the bundle's actions to its net value balance | + +See the [Orchard bundle primitives in rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/shielded/mod.rs). + +### Actions + +Each Orchard action structurally contains one spend and one output. The spend consumes a previously created note (revealing its nullifier), while the output creates a new note (publishing its commitment). Although paired in the same struct, observers cannot link which prior note was spent or what value the new note holds — the zero-knowledge proof ensures privacy. + +Each action publishes: + +| Field | Type | Size | Description | +| --- | --- | --- | --- | +| nullifier | array of bytes | 32 bytes | Unique tag derived from the spent note. Used to prevent double-spending | +| rk | array of bytes | 32 bytes | Randomized verification key for the action's spend authorization signature | +| cmx | array of bytes | 32 bytes | Extracted note commitment for the new note | +| encryptedNote | array of bytes | 216 bytes | Encrypted note payload — 32-byte ephemeral public key + 104-byte note ciphertext + 80-byte out-of-band ciphertext | +| cvNet | array of bytes | 32 bytes | Net value commitment (Pedersen commitment to the action's value contribution) | +| spendAuthSig | array of bytes | 64 bytes | Per-action spend authorization signature — see [Shielded Transition Signing](#shielded-transition-signing) | + +Permanent storage cost per action is [312 bytes](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/shielded/mod.rs#L13-L16) (280 bytes in the note commitment tree + 32 bytes in the nullifier tree). + +See the [serialized action implementation in rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/shielded/mod.rs). + +### Anchors + +An **anchor** is the Sinsemilla root of the note commitment tree at the time the bundle was constructed. Each shielded transition specifies the anchor it was built against; the platform validates that the anchor was previously published. Clients fetch anchors using [`getShieldedAnchors`](../reference/dapi-endpoints-platform-endpoints.md#getshieldedanchors) or [`getMostRecentShieldedAnchor`](../reference/dapi-endpoints-platform-endpoints.md#getmostrecentshieldedanchor). + +### Platform Sighash + +Transitions with transparent fields (Unshield, Shielded Withdrawal, etc.) bind those fields to the Orchard signatures via a platform sighash computed as: + +``` +SHA-256(SIGHASH_DOMAIN || bundle_commitment || extra_data) +``` + +This prevents replay attacks where an attacker substitutes transparent fields while reusing a valid Orchard bundle. See the [platform sighash implementation in rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/shielded/mod.rs#L20-L40). + +## Shielded State Transition Details + +### Shield + +Move credits from one or more [Platform addresses](address-system.md#platform-address) into the shielded pool. The total contributed across address inputs must cover the value being shielded plus the transition fee; excess credits remain in the source addresses. + +| Field | Type | Size | Description | +| --- | --- | --- | --- | +| inputs | map | Varies | Map of source [Platform addresses](address-system.md#platform-address) to (`AddressNonce`, max contribution in credits) pairs | +| actions | array | Varies | Orchard [actions](#actions) (output-only — Shield creates new notes without consuming prior ones) | +| amount | unsigned integer | 64 bits | Credits entering the shielded pool | +| anchor | array of bytes | 32 bytes | [Anchor](#anchors) | +| proof | array of bytes | Varies | Halo 2 proof | +| bindingSignature | array of bytes | 64 bytes | RedPallas binding signature | +| feeStrategy | array | Varies | [Fee deduction strategy](address-system.md#fee-strategy) for address inputs | +| userFeeIncrease | unsigned integer | 16 bits | Extra fee to prioritize processing if the mempool is full | +| inputWitnesses | array | Varies | [Address witnesses](address-system.md#address-witness) for each input | + +:::{note} +Maximum actions per transition: [`max_shielded_transition_actions`](protocol-constants.md). Address witness signatures are excluded from the signable bytes used by the platform sighash. +::: + +See the [implementation in rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transitions/shielded/shield_transition/). + +### Shielded Transfer + +Move credits within the pool between notes. There is no transparent surface — to an outside observer, only the Orchard bundle is visible. + +| Field | Type | Size | Description | +| --- | --- | --- | --- | +| actions | array | Varies | Orchard [actions](#actions) | +| valueBalance | unsigned integer | 64 bits | Net value balance — the fee amount extracted from the shielded pool for this transition | +| anchor | array of bytes | 32 bytes | [Anchor](#anchors) | +| proof | array of bytes | Varies | Halo 2 proof | +| bindingSignature | array of bytes | 64 bytes | RedPallas binding signature | + +:::{note} +Maximum actions per transition: [`max_shielded_transition_actions`](protocol-constants.md). +::: + +See the [implementation in rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transitions/shielded/shielded_transfer_transition/). + +### Unshield + +Move credits from the pool to a [Platform address](address-system.md#platform-address) the sender designates. The unshielded amount becomes spendable through normal address-based transitions. + +| Field | Type | Size | Description | +| --- | --- | --- | --- | +| outputAddress | object | Varies | Destination [Platform address](address-system.md#platform-address) | +| actions | array | Varies | Orchard [actions](#actions) (spends consume shielded notes) | +| unshieldingAmount | unsigned integer | 64 bits | Total credits leaving the pool (recipient amount + fee) | +| anchor | array of bytes | 32 bytes | [Anchor](#anchors) | +| proof | array of bytes | Varies | Halo 2 proof | +| bindingSignature | array of bytes | 64 bytes | RedPallas binding signature | + +:::{note} +The `outputAddress` is bound to the Orchard bundle through the [platform sighash](#platform-sighash) to prevent substitution attacks. Maximum actions per transition: [`max_shielded_transition_actions`](protocol-constants.md). +::: + +See the [implementation in rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transitions/shielded/unshield_transition/). + +### Shield from Asset Lock + +Move credits from a Dash Core (L1) asset-lock transaction directly into the shielded pool, without first funding a Platform address. + +| Field | Type | Size | Description | +| --- | --- | --- | --- | +| assetLockProof | object | Varies | [Asset lock proof](identity.md#asset-lock) (InstantSend or ChainLock) authorizing the funds | +| actions | array | Varies | Orchard [actions](#actions) | +| valueBalance | unsigned integer | 64 bits | Credits entering the shielded pool from the asset lock | +| anchor | array of bytes | 32 bytes | [Anchor](#anchors) | +| proof | array of bytes | Varies | Halo 2 proof | +| bindingSignature | array of bytes | 64 bytes | RedPallas binding signature | +| signature | array of bytes | 65 bytes | ECDSA signature over the signable bytes proving control of the asset-locked output | + +:::{note} +`valueBalance` must be greater than zero and at most `i64::MAX`. The ECDSA signature is excluded from the signable bytes used by the platform sighash. Maximum actions per transition: [`max_shielded_transition_actions`](protocol-constants.md). +::: + +See the [implementation in rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transitions/shielded/shield_from_asset_lock_transition/). + +### Shielded Withdrawal + +Move credits from the pool back to Dash Core (L1). The funds leave Platform entirely rather than landing in a Platform address. + +| Field | Type | Size | Description | +| --- | --- | --- | --- | +| actions | array | Varies | Orchard [actions](#actions) (spends + change outputs) | +| unshieldingAmount | unsigned integer | 64 bits | Total credits leaving the pool (recipient amount + fee) | +| anchor | array of bytes | 32 bytes | [Anchor](#anchors) | +| proof | array of bytes | Varies | Halo 2 proof | +| bindingSignature | array of bytes | 64 bytes | RedPallas binding signature | +| coreFeePerByte | unsigned integer | 32 bits | Core transaction fee rate for the L1 withdrawal transaction | +| pooling | unsigned integer | 8 bits | Withdrawal pooling strategy (see [Identity Credit Withdrawal](identity.md#identity-credit-withdrawal)) | +| outputScript | array of bytes | Varies | Core script of the L1 address receiving the withdrawn funds | + +:::{note} +Transparent fields (`coreFeePerByte`, `pooling`, `outputScript`) are bound to the Orchard bundle through the [platform sighash](#platform-sighash). Maximum actions per transition: [`max_shielded_transition_actions`](protocol-constants.md). +::: + +See the [implementation in rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transitions/shielded/shielded_withdrawal_transition/). + +## Shielded Transition Signing + +Shielded transitions are not signed by an identity public key. The 65-byte `signature` and the `signaturePublicKeyId` fields listed in the [common fields](state-transition.md#common-fields) for identity-signed transitions do not appear on Unshield, Shielded Transfer, or Shielded Withdrawal. Authorization is instead carried by cryptographic primitives attached to the Orchard bundle and, where applicable, to the transparent side of the transition. + +### Orchard bundle signatures + +Every shielded transition includes: + +- **Per-action spend authorization signatures** (`spendAuthSig` on each [action](#actions)). Each is a 64-byte RedPallas signature, produced by the holder of the spent note over the randomized verification key `rk`. The proof binds `rk` to the original spending key, so verifying the signature against `rk` proves the spender is authorized. +- **Binding signature** (`bindingSignature` on the transition). A 64-byte RedPallas signature over the sum of the action value commitments, proving that the actions' net value balance matches the transition's declared value balance. + +### Platform sighash + +Transitions that include transparent fields (Shield, Unshield, Shield from Asset Lock, Shielded Withdrawal) bind those fields to the Orchard bundle through the [platform sighash](#platform-sighash). Any modification to the transparent fields invalidates the Orchard signatures, preventing replay attacks that substitute transparent fields while reusing a valid bundle. + +### Transparent signatures (Shield, Shield from Asset Lock) + +Two shielded transitions also carry transparent signatures over the transparent side of the transition: + +- **Shield** includes an array of [address witnesses](address-system.md#address-witness) (`inputWitnesses`) — one per address input. Each witness proves control of its corresponding Platform address. Address witness signatures are excluded from the bytes that feed the platform sighash (they sign the platform sighash output, not vice-versa). +- **Shield from Asset Lock** includes a 65-byte ECDSA `signature` proving control of the L1 asset-locked output, in the same form used by [Identity Create](identity.md#identity-create). The signature is excluded from the bytes that feed the platform sighash. + +Shielded Transfer, Unshield, and Shielded Withdrawal have no transparent signatures; the Orchard bundle signatures plus the platform sighash provide full authorization. + +## Querying shielded state + +DAPI exposes a set of read-only endpoints for clients that need to fetch anchors, scan encrypted notes, verify nullifier status, or sync incremental nullifier updates. See the [DAPI Platform endpoints reference](../reference/dapi-endpoints-platform-endpoints.md) for request and response shapes: + +- [`getShieldedPoolState`](../reference/dapi-endpoints-platform-endpoints.md#getshieldedpoolstate) +- [`getShieldedAnchors`](../reference/dapi-endpoints-platform-endpoints.md#getshieldedanchors) +- [`getMostRecentShieldedAnchor`](../reference/dapi-endpoints-platform-endpoints.md#getmostrecentshieldedanchor) +- [`getShieldedEncryptedNotes`](../reference/dapi-endpoints-platform-endpoints.md#getshieldedencryptednotes) +- [`getShieldedNullifiers`](../reference/dapi-endpoints-platform-endpoints.md#getshieldednullifiers) +- [`getNullifiersTrunkState`](../reference/dapi-endpoints-platform-endpoints.md#getnullifierstrunkstate) +- [`getNullifiersBranchState`](../reference/dapi-endpoints-platform-endpoints.md#getnullifiersbranchstate) +- [`getRecentNullifierChanges`](../reference/dapi-endpoints-platform-endpoints.md#getrecentnullifierchanges) +- [`getRecentCompactedNullifierChanges`](../reference/dapi-endpoints-platform-endpoints.md#getrecentcompactednullifierchanges) diff --git a/docs/protocol-ref/state-transition.md b/docs/protocol-ref/state-transition.md index 9f310528d..e55d1c76e 100644 --- a/docs/protocol-ref/state-transition.md +++ b/docs/protocol-ref/state-transition.md @@ -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 | 16 bits | The state transition format version (FeatureVersion). Currently `0` for most transitions, `1` for Batch. This is not the global platform protocol version, which is negotiated separately. | -| type | unsigned integer | 8 bits | State transition type (defined in [rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transition_types.rs#L21)):
    `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 withdrawal](identity.md#identity-credit-withdrawal)
    `7` - [identity credit transfer](identity.md#identity-credit-transfer)
    `8` - [masternode vote](#masternode-vote)
    `9` - [identity credit transfer to addresses](address-system.md#identity-credit-transfer-to-addresses)
    `10` - [identity create from addresses](address-system.md#identity-create-from-addresses)
    `11` - [identity topup from addresses](address-system.md#identity-topup-from-addresses)
    `12` - [address funds transfer](address-system.md#address-funds-transfer)
    `13` - [address funding from asset lock](address-system.md#address-funding-from-asset-lock)
    `14` - [address credit withdrawal](address-system.md#address-credit-withdrawal)
    `15` - shield
    `16` - shielded transfer
    `17` - unshield
    `18` - shield from asset lock
    `19` - shielded withdrawal | +| type | unsigned integer | 8 bits | State transition type (defined in [rs-dpp](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transition_types.rs#L21)):
    `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 withdrawal](identity.md#identity-credit-withdrawal)
    `7` - [identity credit transfer](identity.md#identity-credit-transfer)
    `8` - [masternode vote](#masternode-vote)
    `9` - [identity credit transfer to addresses](address-system.md#identity-credit-transfer-to-addresses)
    `10` - [identity create from addresses](address-system.md#identity-create-from-addresses)
    `11` - [identity topup from addresses](address-system.md#identity-topup-from-addresses)
    `12` - [address funds transfer](address-system.md#address-funds-transfer)
    `13` - [address funding from asset lock](address-system.md#address-funding-from-asset-lock)
    `14` - [address credit withdrawal](address-system.md#address-credit-withdrawal)
    `15` - [shield](shielded-pool.md#shield)
    `16` - [shielded transfer](shielded-pool.md#shielded-transfer)
    `17` - [unshield](shielded-pool.md#unshield)
    `18` - [shield from asset lock](shielded-pool.md#shield-from-asset-lock)
    `19` - [shielded withdrawal](shielded-pool.md#shielded-withdrawal) | | 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 | @@ -142,14 +142,13 @@ transition type: | Signing Method | State Transitions | | -------------- | ----------------- | | [Identity](#signing-with-identity) | Batch, Contract create, Contract update, Identity update, Identity credit transfer, Identity credit transfer to addresses, Identity credit withdrawal, Masternode vote | -| [Asset lock](#signing-with-asset-lock) | Identity create, Identity topup, Address funding from asset lock* | -| [Address witness](#signing-with-address-witness) | Identity create from addresses, Identity topup from addresses, Address funds transfer, Address credit withdrawal, Address funding from asset lock* | +| [Asset lock](#signing-with-asset-lock) | Identity create, Identity topup, Address funding from asset lock\*, Shield from asset lock\*\* | +| [Address witness](#signing-with-address-witness) | Identity create from addresses, Identity topup from addresses, Address funds transfer, Address credit withdrawal, Address funding from asset lock\*, Shield\*\* | +| [Shielded (Orchard)](shielded-pool.md#shielded-transition-signing) | Shield\*\*, Shielded transfer, Unshield, Shield from asset lock\*\*, Shielded withdrawal | \* Address funding from asset lock requires both an asset lock signature and address witnesses (`input_witnesses`). -:::{note} -Shield-related state transitions (types 15-19: Shield, ShieldedTransfer, Unshield, ShieldFromAssetLock, ShieldedWithdrawal) are defined in the protocol but their signing methods are not yet documented here. -::: +\*\* Shielded transitions are always authorized by Orchard bundle signatures (per-action `spendAuthSig` plus the transition-level `bindingSignature`). Shield additionally carries address witnesses for its transparent address inputs; Shield from asset lock additionally carries an asset-lock ECDSA signature. :::{note} Address-based state transitions (types 9-14) were introduced in Protocol Version 11. For detailed information on these transitions, see [Address-Based State Transitions](address-system.md). @@ -218,6 +217,12 @@ Public keys can be added to an identity by the identity create or identity updat - Use the private key that derived the public key to sign the hash. - Store the result in the public key's `signature` field. +### Signing Shielded Transitions + +Shielded transitions are not signed by an identity public key or an address private key at the transition level — they do not include `signature` or `signaturePublicKeyId` fields. Authorization is carried instead by Orchard primitives attached to each action and to the bundle as a whole. Shield additionally carries [address witnesses](#signing-with-address-witness) over its address inputs, and Shield from asset lock additionally carries an [asset-lock ECDSA signature](#signing-with-asset-lock). Both `input_witnesses` (on Shield) and `signature` (on Shield from asset lock) are omitted from the bytes that feed the platform sighash. + +See [Shielded Transition Signing](shielded-pool.md#shielded-transition-signing) for the full signing model. + ### Non-signable Fields This table shows the fields that must be excluded when creating state transition signatures. All transitions exclude the signature field. Some transitions contain other fields that must be excluded also. Click the state transition name to see the rs-dpp implementation for additional context. @@ -233,3 +238,7 @@ This table shows the fields that must be excluded when creating state transition | [Identity credit transfer](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/mod.rs#L49-L52) | Exclude | Exclude | N/A | N/A | | [Identity credit withdrawal](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/mod.rs#L44-L47) | Exclude | Exclude | N/A | N/A | | [Masternode vote](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/mod.rs#L49-L52) | Exclude | Exclude | N/A | N/A | + +:::{note} +The table above does not cover shielded transitions, which do not carry transition-level `signature` or `signaturePublicKeyId` fields. See [Signing Shielded Transitions](#signing-shielded-transitions). +:::