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)