diff --git a/dip-0008.md b/dip-0008.md index ce3dbd1..dddf135 100644 --- a/dip-0008.md +++ b/dip-0008.md @@ -15,6 +15,8 @@ 1. [Abstract](#abstract) 1. [Motivation](#motivation) 1. [Prior Work](#prior-work) +1. [Used LLMQ type](#used-llmq-type) +1. [Safe transactions](#safe-transactions) 1. [Signing attempts](#signing-attempts) 1. [Finalization of signed blocks](#finalization-of-signed-blocks) 1. [Handling of signed blocks](#handling-of-signed-blocks) @@ -88,14 +90,56 @@ when receiving funds and removing the possibility of 51% mining attacks. - [DIP 006: Long Living Masternode Quorums](https://github.com/dashpay/dips/blob/master/dip-0006.md) - [DIP 007: LLMQ Signing Requests / Sessions](https://github.com/dashpay/dips/blob/master/dip-0007.md) +## Used LLMQ type + +All signing sessions/requests involved in ChainLocks must use the LLMQ_400_60 LLMQ type. + +## Safe transactions + +In general, all valid blocks could also be considered for ChainLocks. There is a small +risk of confirmed transactions conflicting with InstantSend locks. To resolve these conflicts, +ChainLocks need to be prioritized over InstantSend locks when conflicts arise. + +As such conflict resolution is quite severe and in some sense voids all the security gained +by InstantSend, it is desirable to reduce the probability of such conflicts to practically zero. + +This can be achieved by a change in block template generation. Miners are encouraged to only +include “safe” transactions in blocks. A transaction is considered safe if it is InstantSend +locked or locally known for at least 10 minutes without a conflicting InstantSend lock +appearing in the meantime. The default implementation for block template generation +(as found in Dash Core) will be changed to honor this. + +At the same time, masternodes should only try to sign/lock blocks which include only "safe" +transactions. This means that ChainLocks will only be created when the whole block +is considered "safe". Consequently, the probability of a conflicting InstantSend lock +appearing after the creation of the ChainLock is practically zero. + +This assumes that [DIP-0010 LLMQ based InstantSend](https://github.com/dashpay/dips/blob/master/dip-0010.md) +is already implemented as it changes InstantSend behaviour to try to lock all transactions +instead of just a few selected ones. + +DIP-0010 also implements "retroactive signing of transactions", which guarantees that transactions +are InstantSend locked in a retroactive way if they were unknown before appearing in a +mined block. This prevents blocks which contain unlocked transactions from suppressing +ChainLocks, as it allows the ChainLocks system to sign blocks retroactively as well. + ## Signing attempts -When a new valid block is received by a masternode, it must invoke the [DIP007 +Each masternode should periodically try to sign the current chain tip. When the tip already has a valid +ChainLock, this can be skipped. + +Before actually signing the tip, each masternode should check if all transactions contained in all blocks +between the last ChainLocked block and the current chain tip are "safe" (see previous section). This check +should be limited to a depth of 6 blocks in case there is no known previous ChainLock or if the previous +ChainLock is deeper than 6 blocks. + +When these checks pass, each masternode must invoke the [DIP0007 `SignIfMember` operation](https://github.com/dashpay/dips/blob/master/dip-0007.md#void-signifmemberuint256-id-uint256-msghash-int-activellmqs). -The request id for the operation is `hash(prevBlockHash, attemptNum)` and the +The request id for the operation is `hash("clsig-attempt", blockHeight, attemptNum)` and the message hash is the hash of the new block (`newBlockHash`). The first time this -is attempted, `attemptNum` must be set to `0`. +is attempted, `attemptNum` must be set to `0`. "clsig-attempt" is a static string that +must be prepended by its length (13, as a compactSize uint). In most cases, the majority of the LLMQ will sign the same message hash in the first attempt and thus find consensus. This can be checked with the [DIP007 @@ -122,10 +166,10 @@ consensus has been reached. ## Finalization of signed blocks After a signing attempt has succeeded, another LLMQ must sign the successful -attempt. This is only performed once for each `prevBlockHash` and thus either +attempt. This is only performed once for each `blockHeight` and thus either succeeds or fails without performing additional attempts. -The request id is `prevBlockHash` and the message hash is the block hash of the +The request id is `hash("clsig", blockHeight)` and the message hash is the block hash of the previously successful attempt. After a LLMQ member has successfully recovered the final ChainLocks @@ -134,7 +178,7 @@ message is called `CLSIG` and has the following structure: | Field | Type | Size | Description | |--|--|--|--| -| prevBlockHash | uint256 | 32 | Hash of the previous block | +| height | int32 | 4 | Height of the signed block | | blockHash | uint256 | 32 | Hash of the signed block from the successful attempt | | sig | BLSSig | 96 | Recovered signature | @@ -143,14 +187,11 @@ This message is propagated through the inventory system. Upon receipt, each node must perform the following verification before announcing it to other nodes: - 1. `prevBlockHash` must refer to a block that is part of any locally known -chain - 2. Based on the deterministic masternode list at the chain height of -`prevBlockHash`, a quorum must be selected that was active at the time this -block was mined - 3. The signature must verify against the quorum public key and -`hash(llmqType, quorumHash, prevBlockHash, blockHash)`. `llmqType` and `quorumHash` -must be taken from the quorum selected in 2. + 1. Based on the deterministic masternode list at the given height, a quorum must be + selected that was active at the time this block was mined + 2. The signature must verify against the quorum public key and + `hash(llmqType, quorumHash, hash(height), blockHash)`. `llmqType` and `quorumHash` + must be taken from the quorum selected in 2. ## Handling of signed blocks