mirror of
https://github.com/seigler/dips
synced 2025-07-27 01:36:14 +00:00
Add DIP8 - ChainLocks (#32)
This commit is contained in:
parent
0afc096282
commit
283c6c9938
1 changed files with 239 additions and 0 deletions
239
dip-0008.md
Normal file
239
dip-0008.md
Normal file
|
@ -0,0 +1,239 @@
|
|||
<pre>
|
||||
DIP: 0008
|
||||
Title: ChainLocks
|
||||
Author(s): Alexander Block
|
||||
Special-Thanks: Andy Freer, Samuel Westrich, Thephez, Udjinm6
|
||||
Comments-Summary: No comments yet.
|
||||
Status: Proposed
|
||||
Type: Standard
|
||||
Created: 2018-11-16
|
||||
License: MIT License
|
||||
</pre>
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Abstract](#abstract)
|
||||
1. [Motivation](#motivation)
|
||||
1. [Prior Work](#prior-work)
|
||||
1. [Signing attempts](#signing-attempts)
|
||||
1. [Finalization of signed blocks](#finalization-of-signed-blocks)
|
||||
1. [Handling of signed blocks](#handling-of-signed-blocks)
|
||||
1. [Conflicting successful signing attempts](#conflicting-successful-signing-attempts)
|
||||
1. [Implications of a signed block](#implications-of-a-signed-block)
|
||||
1. [Network partitions](#network-partitions)
|
||||
1. [Initial Block Download](#initial-block-download)
|
||||
1. [Copyright](#copyright)
|
||||
|
||||
## Abstract
|
||||
|
||||
This DIP introduces ChainLocks, a technology for near-instant confirmation
|
||||
of blocks and finding near-instant consensus on the longest valid/accepted
|
||||
chain. ChainLocks leverages LLMQ Signing Requests/Sessions to accomplish
|
||||
this.
|
||||
|
||||
## Motivation
|
||||
|
||||
When a node encounters multiple valid chains, it sets the local "active" chain
|
||||
by selecting the one that has the most accumulated work. This is generally
|
||||
known as the “longest-chain” rule as in most cases it is equivalent to
|
||||
choosing the chain with the most blocks.
|
||||
|
||||
If both chains have the same amount of accumulated work (and in most cases the
|
||||
same block count), a decision can’t be made solely based on the longest-chain
|
||||
rule. In that case, the first chain received by the node is chosen to be the
|
||||
active one and the other chain is put aside. If another block is then received
|
||||
which extends the non-active chain so that it has the most accumulated work, it
|
||||
becomes the active one. For example, even if a chain is currently 6 blocks
|
||||
longer than any other chain, it’s still possible that a shorter chain becomes
|
||||
longer and thus the active one. This is generally known as a chain
|
||||
reorganization.
|
||||
|
||||
The most common situation where this happens is if two miners find a block at
|
||||
approximately the same time. Such a block would race in the network and one
|
||||
part of the network would accept one block as the new active chain while
|
||||
another part of the network would accept the other block. In most cases,
|
||||
whoever finds the next block also indirectly resolves the situation as the new
|
||||
block’s parent block determines which of the chains will be the longest one.
|
||||
This is generally known as orphaning of blocks.
|
||||
|
||||
It might also happen by accident. For example, if parts of the network with a
|
||||
high hashrate are partitioned and miners are unaware of other miners mining on
|
||||
another chain. When the network becomes healthy again, multiple chains will
|
||||
exist that all branch from a common ancestor. While these chains are
|
||||
propagated, one side of the previously partitioned network will have to
|
||||
reorganize their local chain to the chain of the other side.
|
||||
|
||||
It can also happen on purpose if a miner with more hashrate than all other
|
||||
miners combined decides to ignore other miner’s blocks and only mine on top
|
||||
of their own blocks. This is generally known as the 51% mining attack. A miner
|
||||
can even go as far as not publishing any blocks for some time so the remainder
|
||||
of the network is not aware of the attack until they suddenly publish the
|
||||
longer secret chain.
|
||||
|
||||
In all these cases, uncertainty arises for individual recipients of funds. When
|
||||
a reorganization happens, it is not necessary for the new chain to include the
|
||||
same transactions as the old chain. In addition to including new transactions
|
||||
and excluding old transactions, it is possible to include transactions in the
|
||||
new chain which are in conflict with the old chain. This means that a new chain
|
||||
might send funds from the same inputs to another address. This results in the
|
||||
only valid form of double spending possible in Dash (InstantSend is not
|
||||
double-spendable even for this case) and most other Bitcoin based
|
||||
cryptocurrencies.
|
||||
|
||||
This DIP proposes a new method, called ChainLocks, for reducing uncertainty
|
||||
when receiving funds and removing the possibility of 51% mining attacks.
|
||||
|
||||
## Prior work
|
||||
|
||||
- [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)
|
||||
|
||||
## Signing attempts
|
||||
|
||||
When a new valid block is received by a masternode, it must invoke the [DIP007
|
||||
`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
|
||||
message hash is the hash of the new block (`newBlockHash`). The first time this
|
||||
is attempted, `attemptNum` must be set to `0`.
|
||||
|
||||
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
|
||||
`HasRecoveredSig` operation](https://github.com/dashpay/dips/blob/master/dip-0007.md#bool-hasrecoveredsiguint256-id-uint256-msghash-int-activellmqs).
|
||||
This will even hold true in most cases where 2 competing blocks are being
|
||||
propagated inside the network, as only one is able to reach more LLMQ members
|
||||
faster than the other and thus gain a majority in the signing request.
|
||||
|
||||
In some cases however, it is possible that no majority can be reached in the
|
||||
first attempt. This could happen if too many members of the LLMQ are
|
||||
malfunctioning or if more than two blocks are competing. If this happens, a
|
||||
second signing request with an incremented `attemptNum` value must be
|
||||
initiated. To check for a failed attempt, the [DIP007 `IsMajorityPossible`
|
||||
operation](https://github.com/dashpay/dips/blob/master/dip-0007.md#bool-ismajoritypossibleuint256-id-uint256-msghash-int-activellmqs) must be used. An attempt
|
||||
is also considered as failed when it did not succeed after some timeout.
|
||||
|
||||
On failure, another signing request with an incremented `attemptNum` value
|
||||
should be initiated. The new request should use the message hash returned by
|
||||
the [DIP007 `GetMostSignedSession` operation](https://github.com/dashpay/dips/blob/master/dip-0007.md#uint256-getmostsignedsessionuint256-id-int-activellmqs), which is the hash of the block
|
||||
which had the most signatures in the last attempt. After a few attempts, a
|
||||
request should result in a recovered threshold signature which indicates
|
||||
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
|
||||
succeeds or fails without performing additional attempts.
|
||||
|
||||
The request id is `prevBlockHash` and the message hash is the block hash of the
|
||||
previously successful attempt.
|
||||
|
||||
After a LLMQ member has successfully recovered the final ChainLocks
|
||||
signature, it must create a P2P message and propagate it to all nodes. The
|
||||
message is called `CLSIG` and has the following structure:
|
||||
|
||||
| Field | Type | Size | Description |
|
||||
|--|--|--|--|
|
||||
| prevBlockHash | uint256 | 32 | Hash of the previous block |
|
||||
| blockHash | uint256 | 32 | Hash of the signed block from the successful attempt |
|
||||
| attemptNum | uint16 | 2 | The attempt number |
|
||||
| sig | BLSSig | 96 | Recovered signature |
|
||||
|
||||
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(blockHash, attemptNum)`.
|
||||
|
||||
## Handling of signed blocks
|
||||
|
||||
When a new block has been successfully signed by a LLMQ and the `CLSIG` message
|
||||
is received by a node, it should ensure that only this block is locally
|
||||
accepted as the next block.
|
||||
|
||||
If an alternative block for the same height is received, it must be invalidated
|
||||
and removed from the currently active chain since a signed block has already
|
||||
been received. If the correct block is already present locally, its chain
|
||||
should be activated as the new active chain. If the correct block is not known
|
||||
locally, it must wait for this block to arrive and request it from other nodes
|
||||
if necessary.
|
||||
|
||||
If a block has been received locally and no `CLSIG` message has been received
|
||||
yet, it should be handled the same way it was handled before the introduction
|
||||
of ChainLocks. This means the longest-chain and first-seen rules must be
|
||||
applied. When the `CLSIG` message for this (or another) block is later
|
||||
received, the above logic must be applied.
|
||||
|
||||
## Conflicting successful signing attempts
|
||||
|
||||
While the network is operating as expected, it’s not possible to encounter
|
||||
two conflicting recovered signatures for two signing attempts of the same
|
||||
parent block. It is possible for a malicious masternode operator to manually
|
||||
double-sign two different attempts when a close race between two competing
|
||||
blocks occurs. If one of the conflicting signature shares is withheld until the
|
||||
second attempt succeeds and the conflicting signature is then propagated to the
|
||||
network, the two attempts will result in two valid recovered signatures.
|
||||
|
||||
When performing the finalization of successful attempts, the LLMQ members will
|
||||
only try to finalize a single attempt, which is usually the first one to
|
||||
succeed. Only a single attempt will be able to gain a majority during
|
||||
finalization, which removes the possibility of conflicts. In the worst case,
|
||||
finalization completely fails, no `CLSIG` message is created and nodes must
|
||||
fall back to the first-seen and longest-chain rules.
|
||||
|
||||
## Implications of a signed block
|
||||
|
||||
If a block was successfully signed, it can be safely assumed that no chain
|
||||
reorganization before this block can happen, as all nodes would agree to reject
|
||||
blocks with a lower height. This means that each transaction in this block and
|
||||
all previous blocks can be considered irreversibly and instantly confirmed.
|
||||
|
||||
For InstantSend, this also means that the minimum of 6 confirmations of the
|
||||
parent transaction can be removed if the parent transaction is inside or below
|
||||
a signed block.
|
||||
|
||||
## Network partitions
|
||||
|
||||
If there is a network partition, the most likely thing to happen is that just
|
||||
one side is able to mine a signed chain. The other side will encounter
|
||||
non-signed blocks building on top of the last signed block. Miners who observe
|
||||
this must assume that another currently unobserved chain is being built in
|
||||
parallel. Since the parallel chain might be signed and could possibly overtake
|
||||
their own chain after the network is healthy again, miners should act
|
||||
accordingly (e.g. reduce hash power to reduce costs).
|
||||
|
||||
If the network is partitioned to a degree that makes a majority in the
|
||||
responsible LLMQ impossible, all partitions in the network will be unable to
|
||||
produce a signed chain. After the network is healthy again, one part of the
|
||||
network will reorganize itself to the other’s chain after which the
|
||||
responsible LLMQ will sign the new chain tip.
|
||||
|
||||
## Initial Block Download
|
||||
|
||||
While fully synced, nodes will usually receive `CLSIG` messages for new blocks
|
||||
shortly after they are mined. If a node was offline for some time or has to
|
||||
perform an initial block download, the signatures for old blocks will not be
|
||||
present in the initial implementation.
|
||||
|
||||
Nodes should fall back to the plain “longest-chain” and “first-seen”
|
||||
rules in this case until the first block signature for a new block is received.
|
||||
|
||||
We assume that old blocks are secure enough to not encounter any significant
|
||||
forks which could lead to a different chain tip after initial block download is
|
||||
finished. When the chain tip is reached, the first received signature will
|
||||
resolve any ambiguities which might occur in the last few blocks.
|
||||
|
||||
If the need arises to include block signatures in initial block download, we
|
||||
will update this DIP and implementations accordingly.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright (c) 2018 Dash Core Group, Inc. [Licensed under the MIT
|
||||
License](https://opensource.org/licenses/MIT)
|
Loading…
Add table
Add a link
Reference in a new issue