DIP: 0003 Title: Deterministic Masternode Lists Author(s): Samuel Westrich, Alexander Block, Andy Freer, Darren Tapp, Timothy Flynn, Udjinm6, Will Wray Comments-Summary: No comments yet. Status: Final Type: Standard Created: 2018-04-30 License: MIT License
- Abstract
- Motivation and Previous System
- Prior Work
- New On-Chain System
- Registering a Masternode (ProRegTx)
- Updating Masternode Information
- Rules for Updating the Masternode List
- Validation Rules
- Masternode Rewards
- Selecting Quorums
- Appendix A: Reasons for Self Revocation of Operators
- Copyright
We would like to dedicate this DIP to Timothy Flynn who wrote the initial proposal around a Deterministic Masternode list.
This DIP provides on-chain consensus for masternode lists that in turn allow for deterministic quorum derivation and service scoring of masternode rewards in Dash.
In the previous system, each node maintained its own individual masternode list. Masternodes gained entry to that masternode list after the owner created a 1000 Dash UTXO and the masternode broadcast a "masternode broadcast/announcement" P2P message. This in turn set the masternode to a PRE_ENABLED
state in the list maintained by each node. Masternodes then regularly broadcasted ping messages to keep the masternode in ENABLED
state.
The previous system was maintained with consensus mechanisms that predated Satoshi Nakamoto’s solution to the Byzantine Generals Problem. This meant that each node needed to maintain their own individual masternode list with P2P messages and not a blockchain based solution. Due to the nature of the P2P system, there was no guarantee that nodes would come to the same conclusion on what the masternode list ought to look like. Discrepancies might, for example, occur due to a different order of message reception or if messages had not been received at all. This posed some risks in regard to consensus and limited the possible uses of quorums by the system.
As a concrete example, the previous system required implementing workarounds such as "masternode reward voting" which was performed multiple blocks in advance for each block to make sure that consensus would be found and agreed on. Enforcing this consensus however still posed a risk which could have resulted in network wide forking, so a spork to turn off masternode payment enforcement was added to prevent this issue from occurring. The spork was used sporadically after major network updates.
When quorums were used, for example in InstantSend, nodes would sometimes calculate a different quorum set for an InstantSend lock resulting in partially failed locks. This was mostly non-problematic due to the size of the quorum and the quorum selection algorithm, but could still potentially result in individual nodes forking away from the network. This also required implementation of a spork to disable InstantSend related block filtering.
Additionally, the previous system required a complicated and failure prone "masternode sync" after the initial startup of the node. After the blockchain was synced, the node would request the current masternode list, the reward payment votes, and then verify the received list. This process tended to take an unnecessarily long amount of time and sometimes resulted in failure.
Furthermore, the previous system could not be audited for past masternode reward payments. Inclusion of masternode data on-chain will make the chain auditable from the moment of crossover.
The previous system also made certain desirable features infeasible. The integration of a service score was near impossible without a certain consensus. A hardened masternode list also expands on possible system capabilities and makes masternode shares possible.
In the new system, the masternode list is derived entirely from information found on-chain. New masternodes are added by new special transactions called Provider Registration Transactions (abbreviated as ProRegTx). They are only removed by spending the collateral. A ProRegTx is a special transaction which includes either a 1000-Dash collateral payment or a reference to it, along with other payload information (DIP2) described later in this document.
This DIP defines 2 masternode (sub)sets:
- Registered/Full set: All masternodes which were registered on-chain and have not spent their collateral
- Valid subset: All masternodes which are not marked as PoSe banned
Only the valid subset is used in calculations to determine the recipient of the masternode reward. Quorums are also based on the valid subset, but they may include additional constraints that further reduce the subset size. For example, a quorum might only use masternodes with a minimum age.
To join the masternode list, masternode owners must submit a special transaction (DIP2) to the network. This transaction is called a Provider Registration Transaction and is abbreviated to ProRegTx. The ProRegTx must include an output with the 1000 DASH or refer to an already existing unspent output which holds 1000 DASH.
The ProRegTx contains 2 public key IDs and one BLS public key, which represent 3 different roles in the masternode and define update and voting rights. A "public key ID" refers to the hash160 of an ECDSA public key. The keys are:
- KeyIdOwner: This is the public key ID of the masternode or collateral owner. It is different than the key used in the collateral output. Only the owner is allowed to issue ProUpRegTx transactions.
- PubKeyOperator: This is the BLS public key of the masternode operator. Only the operator is allowed to issue ProUpServTx transactions. The operator key is also used while operating the masternode to sign masternode related P2P messages, quorum related messages and governance trigger votes. Messages signed with this key are only valid while the masternode is in the valid set.
- KeyIdVoting: This is the public key ID used for proposal voting. Votes signed with this key are valid while the masternode is in the registered set.
A single key can be used for multiple roles so the owner can also operate the masternode and/or issue proposal votes. Alternately, different keys can be used to delegate duties to other people. For example, owners might decide to use a masternode hosting service instead of self-hosting the masternode. To do so, they would use the operator key provided by the hosting service. The same applies to the voting key, which allows them to assign voting rights to someone else.
The collateralOutpoint of the ProRegTx might refer to an external collateral or to an output which is part of the ProRegTx itself. If the hash of collateralOutpoint is null, it refers to an output of the ProRegTx. If it refers to an external collateral (hash of collateralOutpoint is not null), the collateral must exist and not be spent. The ProRegTx must also prove ownership of external collaterals by setting payloadSigSize and payloadSig to a valid signature which signs the following message:
<magicString><payoutStr>|<operatorReward>|<ownerKeyAddress>|<votingKeyAddress>|<payloadHash>
The individual parts of the message are:
<magicString>
: A fixed string which is always "DarkCoin Signed Message:" with a newline character appended. Please note that existing tools (e.g. the RPC commandsignmessage
) usually add the magicString internally, making it unnecessary to manually add it.<payoutStr>
: The Dash address corresponding to the scriptPayout field of the ProRegTx.<operatorReward>
: The operatorReward field of the ProRegTx.<ownerKeyAddress>
: The Dash address corresponding to the keyIdOwner field of the ProRegTx.<votingKeyAddress>
: The Dash address corresponding to the keyIdVoting field of the ProRegTx.<payloadHash>
: The SHA256 hash of the ProRegTx payload with the payloadSig being empty.
This signature is only required for external collaterals. If collateralOutpoint refers to an output of the ProRegTx, the fact that the ProRegTx was able to move the collateral acts as an implicit proof of ownership. In this case the payloadSig must be empty.
The ProRegTx might have the IP address and port fields set to zero. This will result in the masternode being added to the masternode list in the PoSe-banned state and require the operator to issue a ProUpServTx. This is needed in case the owner wants to delegate the operator role to a hosting service without knowing the IP Address and port in advance.
The ProRegTx also defines the masternode's type and mode. Default masternodes are of type 0, and future types will be defined in an annex document. Different types would introduce additional or different consensus rules towards the masternodes based on future Dash improvement proposals. Masternode types are not updatable, however each type can have multiple operation modes. The operation modes are updatable.
The ProRegTx also specifies the reward for the operator. The percentage of the masternode reward paid to the operator is calculated by dividing the operatorReward field by 100. When the field is set to zero, the owner will get the full reward for every block. If set to a non-zero value, the masternode operator may specify his operator reward payee script in a ProUpServTx. If he does not do so, the full reward goes to the masternode owner.
After a ProRegTx is mined into the chain, the corresponding masternode entry is added to the registered masternode set and therefore eligible for PoSe verification, masternode rewards and quorum participation. If there is a masternode with the same collateral outpoint in the registered masternode set already, it's replaced with the newly registered one.
The special transaction type used for Provider Transactions is 1.
The transaction consists of the following data in the payload area:
Field | Type | Size | Description |
---|---|---|---|
version | uint_16 | 2 | Provider transaction version number. Set to 2 once v19 fork activates |
type | uint_16 | 2 | Masternode type. Default set to 0. |
mode | uint_16 | 2 | Masternode mode. Default set to 0. |
collateralOutpoint | COutpoint | 36 | The collateral outpoint. |
ipAddress | byte[] | 16 | IPv6 address in network byte order. Only IPv4 mapped addresses are allowed (to be extended in the future) |
port | uint_16 | 2 | Port (network byte order) |
KeyIdOwner | CKeyID | 20 | The public key hash used for owner related signing (ProTx updates, governance voting) |
PubKeyOperator | BLSPubKey | 48 | The public key used for operational related signing (network messages, ProTx updates) |
KeyIdVoting | CKeyID | 20 | The public key hash used for voting. |
operatorReward | uint_16 | 2 | A value from 0 to 10000. |
scriptPayoutSize | compactSize uint | 1-9 | Size of the Payee Script. |
scriptPayout | Script | Variable | Payee script (p2pkh/p2sh) |
inputsHash | uint256 | 32 | The SHA256 hash of all the outpoints of the transaction inputs |
platformNodeID | byte[] | 0 or 20 | Dash Platform P2P node ID, derived from P2P public key. Only present for masternode type 1. |
platformP2PPort | uint_16 | 0 or 2 | TCP port of Dash Platform peer-to-peer communication between nodes (network byte order). Only present for masternode type 1. |
platformHTTPPort | uint_16 | 0 or 2 | TCP port of Platform HTTP/API interface (network byte order). Only present for masternode type 1. |
payloadSigSize | compactSize uint | 1-9 | Size of the Signature |
payloadSig | unsigned char[] | Variable | Signature of the hash of the ProTx fields. Signed with the key corresponding to the collateral outpoint in case the collateral is not part of the ProRegTx itself, empty otherwise. |
The different versions are:
Version | Version Description |
---|---|
1 | PubKeyOperator is serialised using legacy BLS scheme |
2 | PubKeyOperator is serialised using basic BLS scheme |
There are multiple ways to update masternodes. The table below details the data affected by each update and the responsible role:
Update Type | Transaction | Issued by | Data updated |
---|---|---|---|
Service | ProUpServTx | Operator Only | IP Address / Port |
Registration | ProUpRegTx | Owner Only | Mode / Payout Script / Voting Key / Operator Key |
Operator Revocation | ProUpRevTx | Operator Only | * No data updated / * Only used to signal the owner that a new ProUpRegTx is required |
To service update a masternode, the masternode operator must submit another special transaction (DIP2) to the network. This special transaction is called a Provider Update Service Transaction and is abbreviated as ProUpServTx. It can only be done by the operator.
An operator can update the IP address and port fields of a masternode entry. If a non-zero operatorReward was set in the initial ProRegTx, the operator may also set the scriptOperatorPayout field in the ProUpServTx. If scriptOperatorPayout is not set and operatorReward is non-zero, the owner gets the full masternode reward.
A ProUpServTx is only valid for masternodes in the registered masternodes subset. When processed, it updates the metadata of the masternode entry and revives the masternode if it was previously marked as PoSe-banned.
The special transaction type used for ProUpServTx Transactions is 2.
The transaction consists of the following data in the payload area:
Field | Type | Size | Description |
---|---|---|---|
version | uint_16 | 2 | ProUpServTx version number. Set to 2 once v19 fork activates |
type | uint_16 | 0 or 2 | Masternode type. Only present for version 2. |
proTXHash | uint256 | 32 | The hash of the initial ProRegTx |
ipAddress | byte[] | 16 | IPv6 address in network byte order. Only IPv4 mapped addresses are allowed (to be extended in the future) |
port | uint_16 | 2 | Port (network byte order) |
scriptOperatorPayoutSize | compactSize uint | 1-9 | Size of the Payee Script. |
scriptOperatorPayout | Script | Variable | Payee script (p2pkh/p2sh) |
inputsHash | uint256 | 32 | The SHA256 hash of all the outpoints of the transaction inputs |
platformNodeID | byte[] | 0 or 20 | Dash Platform P2P node ID, derived from P2P public key. Only present for masternode type 1. |
platformP2PPort | uint_16 | 0 or 2 | TCP port of Dash Platform peer-to-peer communication between nodes (network byte order). Only present for masternode type 1. |
platformHTTPPort | uint_16 | 0 or 2 | TCP port of Platform HTTP/API interface (network byte order). Only present for masternode type 1. |
payloadSig | BLSSig | 96 | Signature of the hash of the ProUpServTx fields. Signed by the Operator. |
The different versions are:
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 |
To registrar update a masternode, the masternode owner must submit another special transaction (DIP2) to the network. This special transaction is called a Provider Update Registrar Transaction and is abbreviated as ProUpRegTx. It can only be done by the owner.
A ProUpRegTx is only valid for masternodes in the registered masternodes subset. When processed, it updates the metadata of the masternode entry. It does not revive masternodes previously marked as PoSe-banned.
The special transaction type used for ProUpRegTx Transactions is 3.
The transaction consists of the following data in the payload area:
Field | Type | Size | Description |
---|---|---|---|
version | uint_16 | 2 | Upgrade Provider Transaction version number. Set to 2 once v19 fork activates |
proTXHash | uint256 | 32 | The hash of the provider transaction |
mode | uint_16 | 2 | Masternode mode |
PubKeyOperator | BLSPubKey | 48 | The public key used for operational related signing (network messages, ProTx updates) |
KeyIdVoting | CKeyID | 20 | The public key hash used for voting. |
scriptPayoutSize | compactSize uint | 1-9 | Size of the Payee Script. |
scriptPayout | Script | Variable | Payee script (p2pkh/p2sh) |
inputsHash | uint256 | 32 | The SHA256 hash of all the outpoints of the transaction inputs |
payloadSigSize | compactSize uint | 1-9 | Size of the Signature |
payloadSig | unsigned char[] | Variable | Signature of the hash of the ProTx fields. Signed by the Owner. |
The different versions are:
Version | Version Description |
---|---|
1 | PubKeyOperator is serialised using legacy BLS scheme |
2 | PubKeyOperator is serialised using basic BLS scheme |
If an operator suspects their keys are insecure or if they wish to terminate service, they can issue a special transaction to the network. This special transaction is called a Provider Update Revocation Transaction and is abbreviated as ProUpRevTx. It can only be done by the operator and allows them to signal the owner through the blockchain to choose a new operator (or the same one with a new non-compromised key).
When a ProUpRevTx is processed, it updates the metadata of the masternode entry by removing the operator and service information and marks the masternode as PoSe-banned. Owners must later issue a ProUpRegTx Transaction to set a new operator key. After the ProUpRegTx is processed, the new operator must issue a ProUpServTx Transaction to update the service-related metadata and clear the PoSe-banned state (revive the masternode).
Appendix A describes potential reasons for a revocation.
The special transaction type used for Provider Update Revoking Transactions is 4.
The transaction consists of the following data in the payload area:
Field | Type | Size | Description |
---|---|---|---|
version | uint_16 | 2 | ProUpRevTx version number. Set to 2 once v19 fork activates |
proTXHash | uint256 | 32 | The hash of the provider transaction |
reason | uint_16 | 2 | The reason for revoking the key. |
inputsHash | uint256 | 32 | The SHA256 hash of all the outpoints of the transaction inputs |
payloadSig | BLSSig | 96 | Signature of the hash of the ProTx fields. Signed by the Operator. |
The different versions are:
Version | Version Description |
---|---|
1 | payloadSig is serialised using legacy BLS scheme |
2 | payloadSig is serialised using basic BLS scheme |
Updating is done on the so called chain-tips list, which is the list valid at the current chain-tip (highest block of the chain). After a new block finishes processing, the updated list then becomes the new current chain-tips list.
The chain-tips list is updated for every new block that is processed. The rules to update the list are the following:
- If a valid ProRegTx is encountered, a masternode entry (identified by the hash of the ProRegTx) is added to the registered set. The entry also contains metadata (IP address, public keys, etc.) found in the ProTx.
- If any transaction in the block spends the collateral of an existing entry in the registered masternode set, the corresponding masternode is removed from the list
- PoSe verification is performed for all masternodes in the valid subset. If the verification for a masternode fails, it is marked as PoSe-banned and thus will be excluded from the valid masternode subset. PoSe verification is defined by DIP 006 and only relies on data available on-chain up to the current chain-tip.
- If a ProUpServTx is found in the block and the referenced masternode is not marked as PoSe-banned, its metadata is updated.
- If a ProUpServTx is found in the block for a masternode that is currently marked as PoSe-banned (3.), the PoSe-banned state is cleared and the masternode gets revived.
- If a ProUpRegTx is found in the block for a registered masternode, it’s metadata is updated. The ProUpRegTx does NOT clear the PoSe-banned state.
Masternodes are identified by the hash of the ProRegTx which created it initially. Masternode lists are not sorted in any way so it is up to the consumer of the list to define a deterministic sorting order (e.g. for payment lists or quorums). It is also up to the consumer of the masternode list to determine additional rules for subset selection.
As each block might result in a different/updated masternode list, it is important to be able to retrieve the masternode list on a per-block basis. For example, this is necessary when validating quorum signatures for a deterministic quorum.
Maintaining additional information locally (not on-chain) for each processed block is recommended so that the masternode list can be recreated or retrieved for every past block.
Reorganisations of the chain must also correctly undo changes to the chain-tips list and update the list based on the new blocks introduced by the reorganisation.
A ProRegTx is invalid if any of these conditions are true:
In the case of type 0:
- collateralOutpoint
hash
is null but an output with 1000 DASH is not present at positionn
of the ProRegTx outputs - collateralOutpoint
hash
is not null but an output with 1000 DASH can't be found in the UTXO specified by thehash
andn
In the case of type 1:
- collateralOutpoint
hash
is null but an output with 4000 DASH is not present at positionn
of the ProRegTx outputs - collateralOutpoint
hash
is not null but an output with 4000 DASH can't be found in the UTXO specified by thehash
andn
Applicable to any type:
- Any KeyId* field is null (KeyIdOwner, KeyIdOperator or KeyIdVoting)
- KeyIdOwner or PubKeyOperator was already used by any entry in the registered masternodes set
- scriptPayout is not a P2PKH or P2SH script
- When scriptPayout is P2PKH script and the public key hash equals any of KeyIdOwner or KeyIdVoting
- ipAddress is set and port is not set to the default mainnet port
- ipAddress is set and not routable or not an IPv4 mapped address
- ipAddress is set and already used in the registered masternodes set
- operatorReward > 10000
- The inputsHash does not match the calculated hash
- collateralOutpoint
hash
is null and payloadSig is not empty (zero size) - collateralOutpoint
hash
is not null and payloadSig is not a valid signature signed with the collateral key - collateralOutpoint
hash
is not null and the referenced collateral is not a P2PKH output
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.
A ProUpServTx is invalid if any of these conditions are true:
- proTxHash can not be found in the registered masternode set
- ipAddress is set and port is not set to the default mainnet port
- ipAddress is set and not routable or not an IPv4 mapped address
- ipAddress is set and already used in another masternode from the registered masternodes set
- scriptOperatorPayout is set and operatorReward of the masternode is 0
- scriptOperatorPayout is set and not a P2PKH or P2SH script
- The inputsHash does not match the calculated hash
- payloadSig is invalid
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.
A ProRegTx or ProUpServTx is invalid if any of these conditions are true (applicable only when type is 1):
- platformP2PPort, platformHTTPPort and port from ipAddress are not distinct.
- platformNodeID is null or is a non-hex string.
- platformNodeID is not unique in the network.
A ProUpRevTx is invalid if any of these conditions are true:
- proTxHash can not be found in the registered masternode set
- The inputsHash does not match the calculated hash
- payloadSig is invalid
The new system removes the need for masternode reward payment votes and allows to deterministically ascertain the recipient of the masternode’s portion of the next block reward.
The new rules to determine the next block’s payee are:
- Take the last block's payee. If it is a regular masternode (type 0), go to step 5.
- If the last HPMN payee was already paid 4 blocks in a row, go to step 5.
- If the last HPMN is not present in the current masternode list anymore, go to step 5.
- Select last HPMN payee as the next block's payee. Return.
- Take the valid masternode subset of the previous block
- Sort the set in ascending order by "testHeight" and “ProRegTx hash”. “testHeight” is determined for each individual entry and equals the “last paid height” (or “registered height” if the masternode was never paid). If the masternode was PoSe-banned before and revived later, the “revival height” of the masternode is used instead of the “registered height”. If the “testHeight” of two masternodes is identical, the ProRegTx hash acts as a deterministic tie breaker.
- Take the first entry of the resulting list and use this as the next block’s payee.
This calculation is performed for every block to enforce proper payment of the block's masternode reward (both payee and amount). Previously, masternode payment enforcement was skipped for superblocks, so miners received the full mining reward. With DIP3, masternode payment enforcement is also performed on superblocks.
The "testHeight" logic in next block payee rule #2 (above) is used to ensure that masternodes must wait at least one full payment cycle before receiving their first reward. This is to incentivise long running masternodes and to avoid paying non-functioning masternodes before PoSe verification can remove them. It also ensures that new masternodes are not able to get a jump start in the payment queue.
The new system enables the deterministic selection of masternode quorums which can be validated at any time if the quorum creation block height (the block height containing the masternode list that the quorum was selected from) is known.
Quorums will be selected based on the requirements of the functionality they support. The only strict rules for quorums are:
- They must be deterministic
- They must be based on the valid masternode subset
Depending on the requirements of the quorum consumer, additional consideration may need to be given to quorum selection including:
- The "depth" (distance from current chain-tip) of the quorum height. This is to prevent using a masternode list that is too old.
- The age of masternodes. This is to exclude masternodes that are too young.
The individual quorum types present in Dash are not subject to this DIP and should be looked up in the appropriate DIPs.
Reason Value | Reason |
---|---|
0 | Not Specified |
1 | Termination of Service |
2 | Compromised Keys |
3 | Change of Keys (Not compromised) |
Copyright (c) 2018 Dash Core Group, Inc. Licensed under the MIT License