diff --git a/README.md b/README.md index 3e8d1cc4..eefc737f 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Number | Layer | Title | Owner | Type | Status [23](dip-0023.md) | Consensus | Enhanced Hard Fork Mechanism | Pasta | Standard | Final [24](dip-0024.md) | Consensus | Long-Living Masternode Quorum Distribution and Rotation | Samuel Westrich & Virgile Bartolo | Standard | Final [25](dip-0025.md) | Peer Services | Compressed Block Headers | gabriel-bjg, Thephez, UdjinM6 | Standard | Proposed -[26](dip-0026.md) | Consensus | Multi-Party Payout | Timothy Munsell, UdjinM6 | Standard | Proposed +[26](dip-0026.md) | Consensus | Masternode Multi-Party Payouts | Timothy Munsell, UdjinM6, Pasta | Standard | Proposed [27](dip-0027.md) | Consensus | Dash Core Credit Pool | Ivan Shumkov, Anton Suprunchuk, Thephez, Samuel Westrich | Standard | Proposed [28](dip-0028.md) | Consensus | Evolution Masternodes | Paul DeLucia, Odysseas Gabrielides, Ɓukasz Klimek, Ivan Shumkov, Samuel Westrich | Standard | Final [29](dip-0029.md) | Consensus | Randomness Beacon For LLMQ Selection | Virgile Bartolo | Standard | Proposed diff --git a/dip-0003.md b/dip-0003.md index a56b4916..fdeb4725 100644 --- a/dip-0003.md +++ b/dip-0003.md @@ -135,10 +135,16 @@ The transaction consists of the following data in the payload area: The different versions are: -| Version | Version Description | -|---------|------------------------------------------------------| -| 1 | PubKeyOperator is serialised using legacy BLS scheme | -| 2 | PubKeyOperator is serialised using basic BLS scheme | +| Version | Version Description | +| ------- | ------------------------------------------------------- | +| 1 | PubKeyOperator is serialised using legacy BLS scheme | +| 2 | PubKeyOperator is serialised using basic BLS scheme | +| 4 | Owner payout list as defined in [DIP-0026](dip-0026.md) | + +[DIP-0026](dip-0026.md) defines version 4 ProRegTx payloads. Version 4 replaces +the single `scriptPayoutSize` and `scriptPayout` fields with an owner payout +list while leaving the existing operator reward and operator payout mechanisms +unchanged. ## Updating Masternode Information @@ -147,7 +153,7 @@ There are multiple ways to update masternodes. The table below details the data | Update Type | Transaction | Issued by | Data updated | | ----------- | ----------- | --------- | ------------ | | Service | ProUpServTx | Operator Only | Masternode addresses | -| Registration | ProUpRegTx | Owner Only | Mode / Payout Script / Voting Key / Operator Key | +| Registration | ProUpRegTx | Owner Only | Mode / Payout Script(s) / Voting Key / Operator Key | | Operator Revocation | ProUpRevTx | Operator Only | \* No data updated / * Only used to signal the owner that a new ProUpRegTx is required | ### Updating Service Features from Operator (ProUpServTx) @@ -177,9 +183,9 @@ The transaction consists of the following data in the payload area: The different versions are: -| Version | Version Description | -|---------|------------------------------------------------------| -| 1 | payloadSig is serialised using legacy BLS scheme | +| Version | Version Description | +| ------- | ----------------------------------------------------------------------------------- | +| 1 | payloadSig is serialised using legacy BLS scheme | | 2 | payloadSig is serialised using basic BLS scheme and type is included in transaction | ### Updating Registrar of Masternode (ProUpRegTx) @@ -207,10 +213,15 @@ The transaction consists of the following data in the payload area: The different versions are: -| Version | Version Description | -|---------|------------------------------------------------------| -| 1 | PubKeyOperator is serialised using legacy BLS scheme | -| 2 | PubKeyOperator is serialised using basic BLS scheme | +| Version | Version Description | +| ------- | ------------------------------------------------------- | +| 1 | PubKeyOperator is serialised using legacy BLS scheme | +| 2 | PubKeyOperator is serialised using basic BLS scheme | +| 4 | Owner payout list as defined in [DIP-0026](dip-0026.md) | + +[DIP-0026](dip-0026.md) defines version 4 ProUpRegTx payloads. Version 4 +replaces the single `scriptPayoutSize` and `scriptPayout` fields with an owner +payout list. ### Operator Self Revoking Transaction (ProUpRevTx) @@ -234,8 +245,8 @@ The transaction consists of the following data in the payload area: The different versions are: -| Version | Version Description | -|---------|------------------------------------------------------| +| Version | Version Description | +| ------- | ------------------------------------------------ | | 1 | payloadSig is serialised using legacy BLS scheme | | 2 | payloadSig is serialised using basic BLS scheme | @@ -267,14 +278,17 @@ Reorganisations of the chain must also correctly undo changes to the chain-tips A ProRegTx is invalid if any of these conditions are true: In the case of type 0: + 1. collateralOutpoint `hash` is null but an output with 1000 DASH is not present at position `n` of the ProRegTx outputs 2. collateralOutpoint `hash` is not null but an output with 1000 DASH can't be found in the UTXO specified by the `hash` and `n` In the case of type 1: + 1. collateralOutpoint `hash` is null but an output with 4000 DASH is not present at position `n` of the ProRegTx outputs 2. collateralOutpoint `hash` is not null but an output with 4000 DASH can't be found in the UTXO specified by the `hash` and `n` Applicable to any type: + 1. Any KeyId* field is null (KeyIdOwner, KeyIdOperator or KeyIdVoting) 2. KeyIdOwner or PubKeyOperator was already used by any entry in the registered masternodes set 3. scriptPayout is not a P2PKH or P2SH script @@ -286,6 +300,12 @@ Applicable to any type: 9. collateralOutpoint `hash` is not null and payloadSig is not a valid signature signed with the collateral key 10. collateralOutpoint `hash` is not null and the referenced collateral is not a P2PKH output +For version 4 ProRegTx and ProUpRegTx payloads, the single `scriptPayout` field +is replaced by the owner payout list defined in [DIP-0026](dip-0026.md). The +version 4 payout-list validation rules in DIP-0026 replace the `scriptPayout` +validation rules above; all other applicable DIP-0003 validation rules continue +to apply unless explicitly replaced by DIP-0026. + Please note that while deploying DIP3, additional and temporary validation rules will apply. The details of these temporary rules will be described in the deployment plan. ### ProUpServTx diff --git a/dip-0026.md b/dip-0026.md index 3fb26a1a..33352045 100644 --- a/dip-0026.md +++ b/dip-0026.md @@ -1,7 +1,7 @@
   DIP: 0026
-  Title: Multi-Party Payouts
-  Authors: Timothy Munsell, UdjinM6
+  Title: Masternode Multi-Party Payouts
+  Author(s): Timothy Munsell, UdjinM6, Pasta
   Special-Thanks: Danny Salman
   Comments-Summary: No comments yet.
   Status: Draft
@@ -12,68 +12,366 @@
 
 ## Table of Contents
 
-* [Table of Contents](#table-of-contents)
-* [Abstract](#abstract)
-* [Motivation and Previous System](#motivation-and-previous-system)
-  * [Problems with the previous system](#problems-with-the-previous-system)
-* [Prior Work](#prior-work)
-* [Registering a Masternode (ProRegTx) and Updating Registrar of Masternode (ProUpRegTx)](#registering-a-masternode-proregtx-and-updating-registrar-of-masternode-proupregtx)
-  * [Validation Rules](#validation-rules)
-* [Copyright](#copyright)
+1. [Abstract](#abstract)
+2. [Motivation](#motivation)
+3. [Prior Work](#prior-work)
+4. [Specification](#specification)
+    1. [Terminology](#terminology)
+    2. [Provider Transaction Version](#provider-transaction-version)
+    3. [Masternode Payout Share](#masternode-payout-share)
+    4. [Registering a Masternode](#registering-a-masternode)
+    5. [Updating Masternode Payout Shares](#updating-masternode-payout-shares)
+    6. [Masternode List State](#masternode-list-state)
+    7. [Masternode Reward Payments](#masternode-reward-payments)
+    8. [Validation Rules](#validation-rules)
+    9. [Special Transaction Filtering](#special-transaction-filtering)
+5. [Deployment and Compatibility](#deployment-and-compatibility)
+6. [Rationale](#rationale)
+7. [Test Cases](#test-cases)
+8. [Security Considerations](#security-considerations)
+9. [Copyright](#copyright)
 
 ## Abstract
 
-This DIP builds on the chain consensus for masternode lists laid forth in DIP0003 and provides for multi-party payout beyond the single owner + operator framework of the current system.
+This DIP extends [DIP-0003: Deterministic Masternode Lists](dip-0003.md) by
+allowing the owner-controlled portion of a masternode reward to be split across
+multiple payout scripts. A masternode may specify between 1 and 8 distinct owner
+payout entries, each with a basis-point reward share. A masternode with one
+owner uses the same structure as a masternode with multiple owners: one payout
+entry with a reward value of 10000.
 
-## Motivation and Previous System
+The existing operator reward mechanism is preserved. If a non-zero operator
+reward was configured and an operator payout script is set, the operator reward
+is subtracted from the masternode reward first. The remaining owner reward is
+then split across the configured owner payout entries.
 
-In the previous system, masternodes gained entry to the masternode list after the owner created a ProRegTx. This transaction provided key IDs for up to two roles that would receive masternode rewards payouts:
+## Motivation
 
-* Owner
-* Operator
+Dash masternodes currently support at most two automatic reward recipients: the
+owner payout address and the operator payout address. This is useful when an
+owner delegates operation to a hosting provider, but it does not support direct,
+protocol-enforced reward distribution among multiple masternode share owners.
 
-### Problems with the previous system
+Without protocol support, shared masternode ownership requires an off-chain
+agreement. One participant receives the masternode reward and then distributes
+funds manually or through an external service. This introduces custodial risk,
+operational delay, accounting complexity, and disputes when the receiving party
+fails to distribute payments correctly.
 
-Paying rewards to only two addresses based on a single value field prevents automatic/trustless sharing of the rewards beyond the owner and/or operator. A more flexible reward payout system is critical for enabling trustless masternode shares and introducing Dash-native DeFi opportunities through staking (among other use cases).
+This DIP allows the blockchain itself to enforce automatic reward distribution
+for the owner-controlled portion of masternode rewards. The registrar owner key
+continues to control masternode registration metadata, including the payout
+split, so this proposal provides protocol-enforced automatic payouts while
+preserving the existing owner-update model from DIP-0003.
 
 ## Prior Work
 
-* [DIP 0002: Special Transactions](https://github.com/dashpay/dips/blob/master/dip-0002.md)
-* [DIP 0003: Deterministic Masternode Lists](https://github.com/dashpay/dips/blob/master/dip-0003.md)
+* [DIP-0002: Special Transactions](dip-0002.md)
+* [DIP-0003: Deterministic Masternode Lists](dip-0003.md)
 
-## Registering a Masternode (ProRegTx) and Updating Registrar of Masternode (ProUpRegTx)
+## Specification
 
-We propose introducing version 2 of these transaction types to replace the `scriptPayout` and `scriptPayoutSize` fields with `payoutShares` and `payoutSharesSize` respectively.
+### Terminology
+
+This DIP uses the following terms:
+
+| Term | Definition |
+| --- | --- |
+| Owner reward | The masternode reward amount remaining after subtracting any operator reward. |
+| Payout entry | One owner payout script and its reward share. |
+| Payout list | The ordered list of owner payout entries for a masternode. |
+| Reward share | A `uint16_t` basis-point value. A value of 10000 represents 100 percent. |
+
+### Provider Transaction Version
+
+DIP-0003 defines the provider transaction `version` field. This DIP defines a new
+version for ProRegTx and ProUpRegTx payloads:
+
+| Name | Value | Description |
+| --- | --- | --- |
+| `MultiPayout` | 4 | Unified owner payout list. |
+
+A version 4 payload is identical to the most recent provider transaction payload
+defined in DIP-0003, except that the single `scriptPayoutSize` and `scriptPayout`
+fields are replaced with a unified `payouts` list. The unified field is used for
+all owner payout configurations, including the single-owner case. All other
+fields, including the BLS serialization scheme and the masternode and Platform
+addressing fields, are unchanged from DIP-0003.
+
+Version 4 applies to the following special transactions:
+
+| Transaction | Special transaction type | Version 4 change |
+| --- | --- | --- |
+| ProRegTx | 1 | Replaces `scriptPayout` with `payouts`. |
+| ProUpRegTx | 3 | Replaces `scriptPayout` with `payouts`. |
+
+This DIP does not change the existing ProUpServTx operator payout field. The
+operator payout remains a separate operator-controlled service update field, and
+the payout list applies only to the owner-controlled portion of the masternode
+reward.
+
+### Masternode Payout Share
+
+Each owner payout entry has the following structure:
 
 | Field | Type | Size | Description |
 | --- | --- | --- | --- |
-| payoutSharesSize | compactSize uint | 1-9 | Size of the Payout Share set |
-| payoutShares | payoutShare[] | 1-32 | A set of `payoutShare` items |
+| scriptPayoutSize | compactSize uint | 1-9 | Size of the payout script. |
+| scriptPayout | Script | Variable | Owner payout script. |
+| reward | uint16_t | 2 | Basis-point share of the owner reward. |
+
+The `reward` field is expressed in basis points. Implementations must interpret
+10000 as 100 percent, 5000 as 50 percent, and 100 as 1 percent.
 
-Each `payoutShare` item should have the following structure:
+The payout list has the following structure:
 
 | Field | Type | Size | Description |
 | --- | --- | --- | --- |
-| scriptPayoutSize | compactSize uint | 1-9 | Size of the Payee Script |
-| scriptPayout | Script | Variable | Payee script (p2pkh/p2sh) |
-| payoutShareReward | uint_16 | 2 | A value from 0 to 10000 |
+| payoutsCount | uint8_t | 1 | Number of payout entries. Must be from 1 to 8. |
+| payouts | MasternodePayoutShare[] | Variable | Ordered owner payout entries. |
+
+The ordering of payout entries is consensus-significant for reward rounding.
+The last payout entry receives the rounding remainder as specified in
+[Masternode Reward Payments](#masternode-reward-payments).
+
+### Registering a Masternode
+
+For version 4 ProRegTx payloads, the `scriptPayoutSize` and `scriptPayout` fields
+of the ProRegTx structure defined in DIP-0003 are replaced, in the same position,
+by the `payoutsCount` and `payouts` fields defined in
+[Masternode Payout Share](#masternode-payout-share). All other ProRegTx fields are
+unchanged from DIP-0003.
+
+For a masternode with one owner, the payout list contains exactly one entry with
+`reward = 10000`.
+
+For external collaterals, the collateral ownership sign string must include the
+new payout list representation instead of the previous single payout string. The
+payout list string is produced by concatenating each payout entry in serialized
+order as:
+
+```text
+:
+```
+
+Entries are joined with commas. `` is the Dash address corresponding
+to the entry's `scriptPayout`. The ProRegTx sign string therefore becomes:
+
+```text
+||||
+```
+
+where `` is as defined in DIP-0003.
+
+### Updating Masternode Payout Shares
+
+For version 4 ProUpRegTx payloads, the `scriptPayoutSize` and `scriptPayout`
+fields of the ProUpRegTx structure defined in DIP-0003 are replaced, in the same
+position, by the `payoutsCount` and `payouts` fields defined in
+[Masternode Payout Share](#masternode-payout-share). All other ProUpRegTx fields
+are unchanged from DIP-0003.
+
+The masternode owner may update the payout list through ProUpRegTx. A payout
+list update does not revive a PoSe-banned masternode, matching existing
+ProUpRegTx behavior.
+
+### Masternode List State
+
+Deterministic masternode state must store the owner payout list for version 4
+masternodes. The previous single `scriptPayout` state field is replaced by the
+unified `payouts` field for version 4 state.
+
+State diffs must report payout-list changes as a single logical field. A
+version 4 state diff that changes any payout entry, payout order, payout script,
+or reward share must include the full replacement payout list.
+
+For compatibility with pre-version-4 masternodes, implementations may internally
+represent legacy `scriptPayout` as a one-entry payout list with `reward = 10000`.
+This compatibility representation must not change the serialization of legacy
+provider transaction payloads or legacy deterministic masternode state.
+
+### Masternode Reward Payments
+
+Masternode reward payment construction proceeds in the following order:
+
+1. Calculate the block's masternode reward using the existing rules.
+2. Apply any Platform credit pool reallocation using the existing rules.
+3. If the selected masternode has a non-zero `operatorReward` and a non-empty
+    operator payout script, calculate:
+
+    ```text
+    operatorAmount = floor(masternodeReward * operatorReward / 10000)
+    ```
 
-To prove ownership of external collaterals, masternode owners must sign the following message and use the resulting signature as the ProRegTx `payloadSig`:
+4. Subtract `operatorAmount` from `masternodeReward`. The result is the owner
+    reward.
+5. For each owner payout entry except the last, calculate:
 
-`||||`
+    ```text
+    entryAmount = floor(ownerReward * reward / 10000)
+    ```
 
-Where `payoutSharesStr` is:
+6. The last owner payout entry receives:
 
-`address([0].)>|[0].|...|address([n].)>|[n].`
+    ```text
+    ownerReward - sum(previous owner payout entry amounts)
+    ```
+
+7. Create one coinbase output for each owner payout entry with a non-zero
+    calculated amount.
+8. If `operatorAmount` is non-zero, create the operator payout output using
+    the existing operator payout script.
+
+The final owner payout entry receives the remainder to guarantee that the total
+owner reward is paid exactly even when integer division truncates earlier
+entries.
+
+Coinbase validation must require every expected masternode payout output by
+amount and script. As with the current masternode payment implementation, the
+relative order of outputs in the coinbase transaction is not consensus
+significant.
 
 ### Validation Rules
 
-A ProRegTx or ProUpRegTx is invalid if any of these conditions are true (in addition to rules defined in DIP0003):
+The following rules apply only to the owner payout list introduced by version 4
+ProRegTx and ProUpRegTx payloads. They do not apply to the existing ProUpServTx
+operator payout field. A version 4 payout list is invalid if any of the following
+conditions are true:
+
+1. `payoutsCount` is less than 1.
+2. `payoutsCount` is greater than 8.
+3. Any payout entry has `reward` less than 100.
+4. Any payout entry has `reward` greater than 10000.
+5. The sum of all `reward` fields is not exactly 10000.
+6. Any `scriptPayout` is not a P2PKH or P2SH script.
+7. The same payout script appears more than once in the payout list.
+8. A P2PKH payout destination equals the owner key ID.
+9. A P2PKH payout destination equals the voting key ID.
+10. A P2PKH payout destination equals the collateral key ID when the collateral
+    output destination can be extracted as a P2PKH destination.
+
+The 100-basis-point minimum is a consensus anti-dust bound. It prevents
+intentionally tiny micro-owner entries from creating nuisance coinbase outputs.
+It is not a guarantee that every possible future block reward will remain above
+policy dust thresholds forever as the block reward declines.
+
+All existing ProRegTx and ProUpRegTx validation rules from DIP-0003 continue to
+apply unless explicitly replaced by this DIP.
+
+### Special Transaction Filtering
+
+Special transaction filters and bloom filters must include every script in a
+version 4 payout list. A filter that matches any owner payout script in the list
+must match the containing ProRegTx or ProUpRegTx in the same manner that a match
+on the current single `scriptPayout` field does.
+
+## Deployment and Compatibility
+
+This DIP is intended to deploy with Dash Core's v24 network upgrade
+(`DEPLOYMENT_V24`). Version 4 ProRegTx and ProUpRegTx payloads are only valid
+after v24 activates.
+
+Before v24 activation:
+
+* Provider transaction versions greater than the current maximum valid version
+  remain invalid.
+* Legacy ProRegTx and ProUpRegTx payload serialization is unchanged.
+* Legacy masternode reward payment behavior is unchanged.
+
+After v24 activation:
+
+* New version 4 registrations may use 1 to 8 owner payout entries.
+* Version 4 registrar updates may change the payout list.
+* Existing legacy masternodes remain valid and continue to use their existing
+  single owner payout script.
+* Existing operator reward behavior remains unchanged.
+
+Implementations should treat legacy single-payout masternodes and version 4
+one-entry payout-list masternodes as equivalent for reward payment purposes, but
+must preserve their distinct serialized provider transaction payloads.
+
+## Rationale
+
+### Unified payout list
+
+Using a payout list for both single-owner and multi-owner masternodes avoids a
+special case where one payout is represented differently from several payouts.
+This makes the new version's semantics clear: every owner reward recipient is a
+payout entry.
+
+### Maximum of 8 owner payout entries
+
+A maximum of 8 owner payout entries provides enough room for common shared
+masternode arrangements while limiting the number of additional coinbase
+outputs and deterministic masternode state size. Larger limits would support
+finer ownership fragmentation, but would increase worst-case coinbase and state
+growth for every paid block involving a highly fragmented masternode.
+
+### Basis-point reward shares
+
+Basis points match the existing `operatorReward` precision and allow the payout
+list to reuse a familiar representation. Requiring the shares to sum to exactly
+10000 avoids ambiguous normalization rules.
+
+### Minimum reward share
+
+The minimum owner payout share of 100 basis points prevents registrations that
+would intentionally create very small recurring coinbase outputs. This limit
+also follows from the maximum payout count: if all 8 entries are used, each
+entry must represent a meaningful owner share.
+
+### Operator reward remains separate
+
+The operator reward serves a different role from owner payout shares. It is
+configured by the owner as a maximum operator percentage, while the operator
+sets the actual operator payout script through ProUpServTx. Keeping this
+mechanism separate preserves hosting-provider delegation without making the
+operator payout script part of the owner payout list.
+
+## Test Cases
+
+Implementations should include tests for the following cases:
+
+1. A version 4 ProRegTx with one payout entry and `reward = 10000` is valid.
+2. A version 4 ProRegTx with 8 distinct payout entries whose rewards sum to
+    10000 is valid.
+3. A version 4 ProRegTx with 0 payout entries is invalid.
+4. A version 4 ProRegTx with 9 payout entries is invalid.
+5. A payout entry with `reward = 99` is invalid.
+6. A payout list whose rewards sum to 9999 or 10001 is invalid.
+7. A payout list containing duplicate scripts is invalid.
+8. A payout list containing a non-P2PKH and non-P2SH script is invalid.
+9. A payout script that reuses the owner, voting, or collateral key is invalid
+    where the corresponding key comparison is possible.
+10. A ProUpRegTx can replace the payout list without reviving a PoSe-banned
+    masternode.
+11. A masternode with an operator payout first subtracts the operator reward and
+    then splits the owner reward across the payout list.
+12. Integer rounding pays the remainder to the last owner payout entry.
+13. Coinbase validation rejects a block missing any expected owner payout output.
+14. Coinbase validation rejects a block paying an expected payout script the
+    wrong amount.
+15. Legacy single-payout masternodes continue to pay exactly as before.
+
+## Security Considerations
+
+This DIP removes the need for an off-chain distributor to manually forward the
+owner portion of masternode rewards to multiple share owners. It does not remove
+the registrar owner's authority to update masternode registration metadata. A
+share arrangement that requires immutable payout rights must use additional
+contractual, wallet, or protocol mechanisms outside the scope of this DIP.
+
+Payout scripts must not reuse owner, voting, or collateral keys for the same
+reason that DIP-0003 restricts current payout key reuse: payout keys may be used
+in less secure wallet environments, while owner, voting, and collateral keys
+control higher-value masternode functions.
 
-  1. Size of `payoutShares` > 32
-  1. Any `payoutShareReward` > 10000
-  1. Sum of `payoutShareReward` for all `payoutShare` != 10000
+The payout count and minimum share limits reduce the risk of using masternode
+registrations to create large numbers of tiny recurring coinbase outputs.
+However, the block reward declines over time, so no fixed basis-point minimum
+can permanently guarantee that every future payout output will remain above all
+policy dust thresholds.
 
 ## Copyright
 
-This document is licensed under the [MIT License.](https://opensource.org/licenses/MIT)
+Copyright (c) 2026 Dash Core Group, Inc. [Licensed under the MIT License](https://opensource.org/licenses/MIT)