add LLMQ DIPs 6 and 7, and supporting BLS docs

also updates special TX type table
This commit is contained in:
thephez 2018-09-07 10:57:39 -04:00 committed by Nathan Marley
parent 15de7a31a6
commit 94c3c7aecb
10 changed files with 899 additions and 0 deletions

View file

@ -11,6 +11,7 @@ may introduce more types.
| 3 | Provider Update Registrar Transaction (ProUpRegTx) | [DIP 003: Deterministic Masternode List](https://github.com/dashpay/dips/blob/master/dip-0003.md) | 1 | Proposed |
| 4 | Provider Update Revocation Transaction (ProUpRevTx) | [DIP 003: Deterministic Masternode List](https://github.com/dashpay/dips/blob/master/dip-0003.md) | 1 | Proposed |
| 5 | Coinbase Transaction (CbTx) | [DIP 004: Simplified Verification of Deterministic Masternode Lists](https://github.com/dashpay/dips/blob/master/dip-0004.md) | 1 | Proposed |
| 6 | Quorum Commitment | [DIP 006: Long Living Masternode Quorums](https://github.com/dashpay/dips/blob/master/dip-0006.md) | 1 | Proposed |
| 8 | Register Subscription Transaction (SubTxRegister) | [DIP 005: Blockchain Users](https://github.com/dashpay/dips/blob/master/dip-0005.md) | 1 | Proposed |
| 9 | Topup BU Credit Subscription Transaction (SubTxTopup) | [DIP 005: Blockchain Users](https://github.com/dashpay/dips/blob/master/dip-0005.md) | 1 | Proposed |
| 10 | Reset BU Key Subscription Transaction (SubTxResetKey) | [DIP 005: Blockchain Users](https://github.com/dashpay/dips/blob/master/dip-0005.md) | 1 | Proposed |

397
dip-0006.md Normal file
View file

@ -0,0 +1,397 @@
# DIP0006 -- Long-Living Masternode Quorums
<pre>
DIP: 0006
Title: Long-Living Masternode Quorums
Author(s): Alexander Block
Special-Thanks: Cofresi, Darren Tapp, Thephez, Samuel Westrich
Comments-Summary: No comments yet.
Status: Proposed
Type: Standard
Created: 2018-09-07
License: MIT License
</pre>
## Table of Contents
1. [Abstract](#abstract)
1. [Motivation](#motivation)
1. [Prior Work](#prior-work)
1. [Supporing documents](#supporting-documents)
1. [Parameters/Variables of a LLMQ and DKG](#parametersvariables-of-a-llmq-and-dkg)
1. [Intra-Quorum Communication](#intra-quorum-communication)
1. [Building the set of deterministic connections](#building-the-set-of-deterministic-connections)
1. [Watch mode](#watch-mode)
1. [LLMQ DKG Network Protocol](#llmq-dkg-network-protocol)
1. [Initialization phase](#1-initialization-phase)
2. [Contribution phase](#2-contribution-phase)
3. [Complaining phase](#3-complaining-phase)
4. [Justification phase](#4-justification-phase)
5. [Commitment phase](#5-commitment-phase)
6. [Finalization phase](#6-finalization-phase)
1. [Mining phase](#7-mining-phase)
1. [Activated LLMQs and threshold signing](#activated-llmqs-and-threshold-signing)
1. [Copyright](#copyright)
## Abstract
This DIP defines Long Living Masternode Quorums (LLMQ). A LLMQ is a deterministic subset of the global deterministic masternode list. Such a quorum is formed with the help of a distributed key generation (DKG) protocol and is supposed to be active for a long time (e.g. days). Multiple quorums are kept alive at the same time, allowing load balancing between these quorums. The main task of a LLMQ is to perform threshold signing of consensus related messages.
## Motivation
Masternode Quorums are already used in Dash, for example in InstantSend and Masternode payment voting. These are however short living and very small (10 members). Such a quorum is created per InstantSend input and requires the network to fully propagate one vote per quorum member.
These quorums do not scale very well, as full propagation of all votes to the full network with larger quorums would very likely overload the network. It is also not practical to store voting results on-chain, as too many signatures would have to be stored in blocks.
New functionality and use cases which are currently planned require much larger quorums and also the storage of voting results on-chain.
Long Living Masternode Quorums and BLS M-of-N Threshold signatures provide a solution which allows us to reduce the network message quantity to 1 message per signing session (e.g. InstantSend input), regardless of the quorum size. Only the quorum itself has to keep track of all the messages which are part of a signing session. The quorum can then discard all intermediate messages (signature shares) after a final recovered threshold signature has been created and only this recovered threshold signature needs to be propagated network-wide.
## Prior work
- [Transaction Locking and masternode Consensus: A Mechanism for Mitigating Double Spending Attacks](https://github.com/dashpay/docs/blob/master/binary/Dash%20Whitepaper%20-%20Transaction%20Locking%20and%20Masternode%20Consensus.pdf)
- [DIP 002: Special Transactions](https://github.com/dashpay/dips/blob/master/dip-0002.md)
- [DIP 003: Deterministic Masternode Lists](https://github.com/dashpay/dips/blob/master/dip-0003.md)
- [Secure Distributed Key Generation for Discrete-Log Based Cryptosystems](https://pdfs.semanticscholar.org/bf9e/630c13f570e2df05b6dcce3ea987015af7c3.pdf)
- [DFINITY Consensus System](https://dfinity.org/pdf-viewer/pdfs/viewer?file=../library/dfinity-consensus.pdf)
## Supporting documents
LLMQs are highly dependent on the BLS Signature Scheme and more advanced BLS schemes. The following supporting documents describe these topics. It is advised to first read and understand these before continuing with this DIP.
- [BLS Signature Scheme](dip-0006/bls_signature_scheme.md)
- [BLS M-of-N Threshold Scheme and Distributed Key Generation](dip-0006/bls_m-of-n_threshold_scheme_and_dkg.md)
## Parameters/Variables of a LLMQ and DKG
The LLMQs DKG protocol and threshold signing details are controlled by a set of configuration parameters. The most notable parameters are the quorum size and the threshold size necessary to recover a valid threshold signature. The intention is to allow multiple types of LLMQs and DKGs to be active at the same time, as different use cases might require different performance and security characteristics.
We will refer to these parameters and variables multiple times in the following sections.
| Parameter | Description |
|--|--|
| quorumSize | The size of the quorum, e.g. 10, 200 or 400. This parameter has the highest influence on the performance of the DKG. A small DKG for a small LLMQ can be performed in a few seconds, while a large LLMQ can take more than a hour to complete. This is identical to the “n” in m-of-n. |
| quorumMinSize | Minimum number of valid members for quorum to be considered valid after the DKG has removed bad members. |
| quorumThreshold | The minimum number of threshold signature shares required to recover a threshold signature. It also influences the DKG as it is the minimum number of valid members to create a valid premature commitment and final commitment. This value should be at least 51% of the quorumSize. This is identical to the “m” in m-of-n. |
| quorumMinMemberAge | Minimum number of blocks a deterministic masternode must be confirmed on-chain before it is considered as a LLMQ member |
| quorumNeighborConnections | Number of connections to establish to neighbor nodes as described in “Intra-Quorum Communication” |
| quorumDiagonalConnections | Number of connections to establish to diagonal nodes as described in “Intra-Quorum Communication” |
| quorumDkgInterval | The number of blocks between two DKG sessions. If set to 576 for example, a new DKG session will start once per day. |
| quorumDkgPhaseBlocks | Number of blocks a single DKG phase is active. It must be high enough to allow all members to exchange all required messages. It must also be high enough to take block time variances into account. |
| badVotesThreshold | Threshold for votes on bad members. If >=badVotesThreshold members have voted on another member to be bad, that member is also considered bad locally. |
List of variables per DKG session:
| DKG Session variable | Description |
|--|--|
| quorumBlock | The first block of a DKG session. |
| quorumHeight | The height of quorumBlock. Can be calculated with “curHeight - (curHeight % quorumDkgInterval)” |
| quorumHash | The hash of the quorumBlock and the identifier for the LLMQ which is built in the current DKG session. |
## Intra-Quorum Communication
The DKG and the signing sessions performed after LLMQ activation require many messages (up to one per phase and per member) to be propagated. Most of these messages are not of interest for nodes outside the LLMQ. Using full propagation (to all nodes) of all these messages would slow down the DKG and signing sessions dramatically. It would also impact the performance and stability of the whole network.
As a solution, we introduce the concept of “Intra-Quorum Communication”. Each LLMQ member is required to connect to a deterministically selected set of neighbor members and keep these connections open for the whole DKG and quorum lifetime. The way the required connections are determined ensures that there is always a path with low numbers of hops from each member to each other member. It also ensures that failure of individual members in the LLMQ does not result in total failure of the DKG and LLMQ.
When messages need to be propagated to all other members, the members will then only push inventory items and messages to this deterministic set of connection. The other members will perform the same, until the message is propagated to the whole LLMQ.
### Building the set of deterministic connections
Every member of the quorum has to build its own list of deterministic quorum connections. This is done the following way:
1. Build the deterministic list of quorum members (See Initialization Phase of the DKG protocol). “listSize” is the size of this list.
2. Loop through the list until the member finds itself in the list. The index at which it finds itself is called “i”.
3. Loop quorumNeighborConnections times, with “n” being the loop index. Calculate “c = (i + 1 + n) % listSize” for each loop iteration. If the resulting index does not equal to “i” (ourself), add the address of the masternode at index “c” to the set of deterministic connections.
4. Calculate “startIdx = (i + listSize / 2 - (quorumDiagonalConnections / 2) * quorumNeighborConnections) % listSize”.
5. Loop quorumDiagonalConnections times, with “n” being the loop index. Calculate “c = (startIdx + n * quorumNeighborConnections) % listSize” for each loop iteration. If the resulting index does not equal to “i” (ourself), add the address of the masternode at index “c” to the set of deterministic connections.
When adding connections to the set of deterministic connections, duplicates should be ignored, meaning that every connection should exist only once in the set.
The process can be imagined as a circle of nodes. In the first loop, each node connects to a few of his neighbors (e.g. the next 4 nodes). This gives good connectivity and low failure rates, but might result in slow propagation as distant nodes require more hops for each message. Thus, the second loop lets each node connect to a few distant nodes which are diagonal to itself on the circle. This builds shortcuts in the circle that allow for more parallel propagation and reduced failure rates.
![Building intra-quorum connections](dip-0006/intra-quorum-comm.png)
Most messaging between members is performed using the inventory system of Dash. This means that members will first send INV messages to other members and respond to GETDATA messages. Some communication messages, however, will be directly sent (see [DIP007 - LLMQ Signing Requests/Sessions](https://github.com/dashpay/dips/blob/master/dip-0007.md)) to quorum members without using the inventory system.
### Watch mode
Even though the DKG and signing messages are not important for other nodes, it must be possible for arbitrary nodes to watch the DKG and quorum communication. This is useful if someone wants to debug the DKG sessions and LLMQ signing sessions. It also increases the transparency in this trustless system, as it allows third parties to verify the correctness of DKG sessions.
To watch quorum communication, a node must connect to one or more arbitrary quorum members and send the “qwatch” message to these members. The members are then required to send all quorum-related messages to this node, even though it is not part of the deterministic connection set.
## LLMQ DKG Network Protocol
The DKG Network protocol is based on the DKG Protocol described in BLS M-of-N Threshold Scheme and Distributed Key Generation. The linked document only describes the mathematical basics of Shamirs Secret Sharing and the DKG. This section extends the basics by adding the required network protocol details.
A new LLMQ is built periodically in a fixed interval (quorumDkgInterval). The interval is measured in number of blocks. After a LLMQ has been successfully built, it is committed/mined on-chain. The new LLMQ only becomes active and starts to do the actual work (threshold signing) after the block is processed.
Building a LLMQ consists of 7 phases:
1. Initialization
2. Contribution
3. Complaining
4. Justification
5. Commitment
6. Finalization
7. Mining
Each phase lasts for multiple blocks (quorumDkgPhaseBlocks) to ensure that all members are able to send, receive, verify and relay all messages belonging to a phase.
### 1. Initialization phase
In this phase, the members of the new quorum are determined. This process is fully deterministic and results in exactly the same list seen by all members and observers.
1. Retrieve the deterministic masternode list which is valid at quorumHeight
2. Remove all entries from the list that are not confirmed on-chain in at least quorumMinMemberAge blocks
3. Calculate hash(proTxHash, quorumHash) for each entry in the list
4. Sort the resulting list by the calculated hashes
5. Take the first quorumSize entries from this list and use the corresponding masternodes as members list
6. Check if our masternode is part of this list. If not, we stop participating in the DKG.
After the members list is built, the LLMQ members start to initiate the connections to the deterministic set of quorum connections as described in the “Intra-Quorum Communication” section.
### 2. Contribution phase
Each member of the LLMQ will generate its own contribution to the DKG and then relay it. At the same time, each member will receive the contributions of all other members and verify the individual contributions.
A contribution consists of a “verification vector” and an individual secret key contribution for all members (including for itself). The verification vector is meant to be public and can be seen by all other members. It resembles the public P(x) polynomial described in the BLS M-of-N Threshold Scheme.
The secret key contributions are meant to be private and must only be visible by the members for which they were generated. The secret key contributions are the result of the evaluation of the private S(x) polynomial.
To make the secret key contributions private, each secret key contribution is encrypted using an Integrated Encryption Scheme (BLS-Diffie-Hellman + AES256 + CBC). The recipient key is the BLS public operator key of the targeted masternode.
The whole contribution (verification vector + secret key contributions) results in a single message which must be relayed/propagated to all other members. The format of the message is described at the bottom of this section.
Each receiver of a contribution message must first perform some basic validation of the message on receival. These include:
1. The quorumHash must match the current DKG session
2. The proTxHash must belong to a member of the LLMQ
3. The verification vector must have exactly as many entries as the configured quorumThreshold
4. The verification vector should not have any duplicates
5. The number of secret key contributions must match the total quorum size
6. The signature of the message must be valid and signed with the operator key of the contributing masternode
If the basic verification succeeds, the message must be relayed to all other members, even if further verification of the secret key contribution fails.
After relaying, the receiving member should try to decrypt and verify the secret key contribution which belongs to itself. If this fails, the contributing member must be marked for later complaining. To verify a secret key contribution, the receiver must use the verification vector of the contributor as the public polynomial P(x) and evaluate it with its own BLS id (the proTxHash). The resulting public key must match the public key calculated from the secret key contribution.
The reason these messages must be relayed independently from secret key verification is that only one member in the quorum is able to perform verification on an individual secret key contribution. A dishonest member might only lie to a single member and still be honest to other members. Without relaying such messages, individual members of the quorum might end up not receiving their honest contribution. Dishonest members are later handled in the complaining and justification phases.
If a member sends multiple contribution messages, they must be marked as bad immediately. In this case only up to 2 messages should be relayed to the rest of the quorum. It doesnt matter which ones are relayed since this is only done to ensure that all members see the bad behavior.
The internal Dash message name is `qcontrib` and the format of the message is:
| Field | Type | Size | Description |
|--|--|--|--|
| quorumHash | uint256 | 32 | The quorum identifier
| proTxHash | uint256 | 32 | The proTxHash of the contributing member
| vvecSize | compactSize uint | 1-9 | The size of the verification vector
| vvec | BLSPubKey[] | 64 * vvecSize | The verification vector
| ephemeralPubKey | BLSPubKey | 64 | Ephemeral BLS public key used to encrypt secret key contributions
| skCount | compactSize uint | 1-9 | Number of encrypted secret key contributions
| skContributions | byte[] | 32 * skCount | Secret key contributions encrypted to recipient masternodes BLS public operator key
| sig | BLSSig | 32 | BLS signature, signed with the operator key of the contributing masternode
### 3. Complaining phase
In the previous phase, members have to keep track of other members which sent invalid secret key contributions. In the complaining phase, a complaint message is created based on this information and relayed to the other members of the LLMQ. The format of this message is described at the bottom of this section.
Each receiver of a complaint message must first perform some validation of the message received. This includes:
1. The quorumHash must match the current DKG session
2. The proTxHash must belong to a member of the LLMQ
3. The byte size of the bad members and complaints bitvectors must match “(quorumSize + 7) / 8”
4. No out-of-range bits should be set in byte representation of the bad members and complaints bitvectors
5. The signature of the message must be valid and signed with the operator key of the contributing masternode
If verification succeeds, the message must be relayed to all other members.
Each set bit in the bad members bitvector represents another member for which no valid contribution message was received by the complainer. The index of a set bit is also the index into the members list. This information is meant to be a vote and is not trusted on its own. Only if enough (>=badVotesThreshold) complainers marked another member as bad, the member is locally marked as bad. This is intended to catch late-comers who sent their contribution on the brink of a phase transition (Contribution->Complaint). Otherwise the DKG might end up being split and each member having a different view on the state.
Each set bit in the complaints bitvector represents another member which the sender of the complaint message is complaining about. The index of a set bit is also the index into the members list.
The receiver must take note of all complaints and later verify that the members which were complained about do a honest justification.
Its theoretically possible that a member is lying about another member and thus complains even though the other member was honest. In that case the quorum can not know who is lying and who is honest, and thus must handle both cases identically (expect a justification).
The receiver must also check if a complaint against itself has been sent. In this case it must note this and later send a justification, even if all contributions previously sent were honest.
If this phase is reached and another member did not send any contribution message, that member is immediately marked as bad and not considered for further justification. This is because only the initial contribution message contains the verification vector necessary to do further verification and finalization. It is not intended to give members a second chance to publish a verification vector, as this would result in inconsistent views on the DKG state.
If a member sends multiple complaint messages, it must be marked as bad immediately. In this case only up to 2 messages should be relayed to the rest of the quorum. It doesnt matter which ones are relayed since this is only done to ensure that all members see the bad behavior.
The internal Dash message name is `qcomplaint` and the format of the message is:
| Field | Type | Size | Description |
|--|--|--|--|
| quorumHash | uint256 | 32 | The quorum identifier
| proTxHash | uint256 | 32 | The proTxHash of the complaining member
| badBitSize | compactSize uint | 1-9 | Number of bits in the bad members bitvector
| badMembers | byte[] | (bitSize + 7) / 8 | The bad members bitvector
| complaintsBitSize | compactSize uint | 1-9 | Number of bits in the complaints bitvector
| complaints | byte[] | (bitSize + 7) / 8 | The complaints bitvector
| sig | BLSSig | 32 | BLS signature, signed with the operator key of the contributing masternode
### 4. Justification phase
In this phase, each member that was previously complained about must justify for a valid contribution. Justification is only allowed for members who sent a contribution and is not allowed for members previously marked as bad.
Justification means that a member has to reveal the secret key contribution that it had initially encrypted and sent to the complainer. This way all other members can verify if the secret key contribution is valid. If the secret key contribution is invalid, the justifier is immediately marked as bad. If the secret key contribution is valid, the complained state for the specific complainer is removed from the justifier. Verification of the published secret key contribution is the same as in the contribution phase, with the difference that the BLS id used in the polynomial evaluation is the one of the justifier instead of the one of the verifier. If verification fails, the justifying member must be marked as bad.
Revealing individual secret key contributions is not a security risk, as long as not all secret key contributions of a single member are revealed. If this happens, it is identical to revealing a single aggregated secret key contribution of a single member. For this to happen, all members would have to complain about the same member, which is unlikely to happen (assuming the member is honest).
Each receiver of a justification message must first perform some validation of the message on receival. This includes:
1. The quorumHash must match the current DKG session
2. The proTxHash must belong to a member of the LLMQ
3. The size of the skContributions vector must not exceed the quorum size
4. Each entry in skContributionMembers must be in the bounds of quorumSize
5. No duplicate entries in skContributionMembers
6. No duplicate entries in skContributions
7. The signature of the message must be valid and signed with the operator key of the contributing masternode
If verification succeeds, the message must be relayed to all other members.
If a member sends multiple justification messages, it must be marked as bad immediately. In this case only up to 2 messages should be relayed to the rest of the quorum. It doesnt matter which ones are relayed since this is only done to ensure that all members see the bad behavior.
The internal Dash message name is `qjustify` and the format of the message is:
| Field | Type | Size | Description |
|--|--|--|--|
| quorumHash | uint256 | 32 | The quorum identifier
| proTxHash | uint256 | 32 | The proTxHash of the justifying member
| skContributionsCount | compactSize uint | 1-9 | Number of unencrypted secret key contributions
| skContributionMembers | uint32[] | 4 * count | Indexes of the members for which justifications are provided
| skContributions | BLSSecKey[] | 32 * count | Unencrypted secret key contributions for the members contained in skContributionMembers
| sig | BLSSig | 32 | BLS signature, signed with the operator key of the contributing masternode
### 5. Commitment phase
In this phase, each member must collect all contributions from all members not marked as bad. The members then build the final quorum verification vector from the individual verification vectors of the members. The members also create their own threshold secret key share from the secret key contributions received by all valid members.
The quorum verification vector is calculated by aggregating all valid members verification vectors into a single verification vector. The quorum verification vector is equal to the aggregated public polynomial Pa(x) described in the BLS M-of-N Threshold Scheme. The secret key share is the aggregation of all valid members secret key contributions. The quorum public key is the first element (the free coefficient) of the quorum verification vector.
The member must then create a premature commitment message which contains the quorum public key, the hash of the quorum verification vector and a bitset of the valid members.
The message is not signed as usual, but instead a commitment hash is created and then signed twice, once with the members operator key and once with the calculated threshold secret key share. The commitment hash is “hash(quorumHash, validMembers, quorumPublicKey, quorumVvecHash)”.
The operator signature allows other members to verify that the message originated from this member. The threshold signature allows other members to verify that the commitment is valid and that the member successfully calculated his secret key share. Both signatures later also allow to aggregate multiple premature commitments into a final commitment.
Each receiver of a premature commitment message must first perform some basic validation of the message. These include:
1. The quorumHash must match the current DKG session
2. The proTxHash must belong to a member of the LLMQ
3. The byte size of the validMembers bitvector must match “(quorumSize + 7) / 8”
4. No out-of-range bits should be set in the byte representation of of the validMembers bitvector
5. The number of set bits in the validMembers bitvector must be at least >= quorumThreshold
6. The sig must validate against the commitmentHash and the committing members operator key
If verification succeeds, the message must be relayed to all other members.
After relaying, further verification must be performed:
1. The quorumPublicKey must match the quorum public key calculated by the verifying member, based on the contributions of the members marked as valid in validMembers
2. The quorumVvecHash must match the hash of the quorum verification vector calculated by the verifying member, based on the contributions of the members marked as valid in validMembers
3. The quorumSig must validate against the commitmentHash and the committing members threshold public key share, which must be calculated before. The public key share is calculated by evaluating the quorum verification vector as a polynomial Pa(x) with x being the signing members BLS id (proTxHash).
If this verification succeeds, the premature commitment must be added to the set of commitments which are later taken into consideration for final commitments. If this verification fails, the premature commitment must be ignored for final commitments.
The reason why premature commitments must be relayed even if further verification fails is that it might be unclear if the validating member is the one missing crucial information or if the other member is dishonest. If the majority (>= quorumThreshold) of the quorum determines that the premature commitment is valid, it is very likely that the validating member is the one missing crucial information. If the other member is dishonest, all other members will come to the same conclusion and later ignore the premature commitment when final commitment happens.
The internal Dash message name is `qpcommit` and the format of the message is:
| Field | Type | Size | Description |
|--|--|--|--|
| quorumHash | uint256 | 32 | The quorum identifier
| proTxHash | uint256 | 32 | The proTxHash of the committing member
| validMembersSize | compactSize uint | 1-9 | Bit size of the validMembers bitvector
| validMembers | byte[] | (bitSize + 7) / 8 | Bitset of valid members in this commitment
| quorumPublicKey | BLSPubKey | 64 | The quorum public key
| quorumVvecHash | uint256 | 32 | The hash of the quorum verification vector
| quorumSig | BLSSig | 32 | Threshold signature, signed with the threshold signature share of the committing member
| sig | BLSSig | 32 | BLS signature, signed with the operator key of the contributing masternode
### 6. Finalization phase
In this phase, all members of the quorum will collect all locally valid premature commitments and build final commitments from these. Only premature commitments with the same set of valid members, the same quorum public key and the same quorum verification vector hash can be aggregated into a single final commitment. Also, a final commitment can only be created if at least quorumThreshold valid premature commitments are present.
To aggregate multiple premature commitments into a single final commitment, the following must be performed:
1. Take all premature commitments for the same set of valid members, quorum public key and quorum verification vector hash.
2. If the number of collected premature commitments is less then the quorumThreshold, skip this set of premature commitments and try another one.
3. Create a final commitment and set the quorumHash, quorumPublicKey and quorumVvecHash to the values determined in 1.
4. Build a bitset of size quorumSize and set all bits for all members of the collected premature commitments
5. Set the signersSize and signers field of the final commitment to this bitset.
6. Perform a BLS signature aggregation for all operator signatures found in the premature commitments. Set the sig field of the final commitment to the result of the aggregation.
7. Perform a BLS threshold signature recovery based on the quorumSigs of the premature commitments. Set the quorumSig field of the final commitment to the result of the recovery.
The resulting final commitment must then be relayed to ALL full nodes of the network, including non-masternodes and masternodes which are not members of this quorum. It should not be relayed to SPV nodes. The message contains all the necessary information required to validate all upcoming quorum signing results. The message is also later used by miners (thus, full propagation is required) to mine it on-chain, which finally activates the quorum.
Each receiver (which might be non-members) of a final commitment message must first perform some basic validation of the message when it is received. These include:
1. The quorumHash must match the current DKG session
2. The byte size of the signers and validMembers bitvectors must match “(quorumSize + 7) / 8”
3. No out-of-range bits should be set in byte representation of the signers and validMembers bitvectors
4. The number of set bits in the signers and validMembers bitvectors must be at least >= quorumThreshold
5. The quorumSig must validate against the quorumPublicKey and the commitmentHash. As this is a recovered threshold signature, normal signature verification can be performed, without the need of the full quorum verification vector. The commitmentHash is calculated in the same way as in the commitment phase.
6. The sig must validate against the commitmentHash and all public keys determined by the signers bitvector. This is an aggregated BLS signature verification.
It is important to note that in this phase, we can not perform full verification of the quorum verification vector. This is because all nodes (including non-members) must come to the same conclusion. This is still secure, as final commitments are only valid if at least quorumThreshold members have signed the same commitmentHash.
If verification succeeds, the final commitment must be added to the set of minable final commitments.
It is possible and valid if multiple final commitments are propagated for the same DKG session. These should however only differ in the number of signers, which can be ignored as long as there are at least quorumThreshold signers. The set of valid members for these final commitments should however always be the same, as all members only create a single premature commitment. This means, that only one set of valid members, and thus only one quorum verification vector and quorum public key can gain a majority. If the threshold is not reached, there will be no valid final commitment.
The internal Dash message name is `qfcommit` and the format of the message is:
| Field | Type | Size | Description |
|--|--|--|--|
| version | uint16_t | 2 | Version of the final commitment message
| quorumHash | uint256 | 32 | The quorum identifier
| signersSize | compactSize uint | 1-9 | Bit size of the signers bitvector
| signers | byte[] | (bitSize + 7) / 8 | Bitset representing the aggregated signers of this final commitment
| validMembersSize | compactSize uint | 1-9 | Bit size of the validMembers bitvector
| validMembers | byte[] | (bitSize + 7) / 8 | Bitset of valid members in this commitment
| quorumPublicKey | BLSPubKey | 64 | The quorum public key
| quorumVvecHash | uint256 | 32 | The hash of the quorum verification vector
| quorumSig | BLSSig | 32 | Recovered threshold signature
| sig | BLSSig | 32 | Aggregated BLS signatures from all included commitments
### 7. Mining phase
After final commitments have been propagated in the network, miners should take the best final commitment for a DKG session and mine it into the next block. The best final commitment is simply the one with the most signers.
A final commitment is mined in the payload of a new special transaction (DIP2). The special transaction is called “quorum commitment” and uses type=6. This special transaction has no inputs and no outputs and thus also pays no fee. This requires lifting consensus rules to allow no-input/no-output transactions for this special transaction.
As this special transaction pays no fees, miners generally dont have an incentive to include the transaction into a new block. To solve this, we make the special transaction mandatory by consensus rules, meaning that exactly one quorum commitment transaction MUST be included in every block while in the mining phase and until a valid commitment is present in a block.
If a DKG failed or a miner did not receive a final commitment in-time, the quorum commitment inside the block must have the quorumHash set to hash(quorumHash, newTipHeight). Also, the signers and validMembers bitsets should be set to the quorumSize and all bits set to zero. All other fields must be set to the null representation of the fields types. The special handling of the quorumHash ensures that all null commitments result in a different transaction hash.
With these new consensus rules, the incentives for miners are turned around. Instead of requiring an incentive to include it in a block, we remove the incentive to leave it out. Whatever the miner decides, the space required for the commitment is always used. If a miner still decides to be dishonest, other honest miners will include the special transaction in one of the next blocks.
These consensus rules are only applied while the DKG is in the mining phase. After a block is mined that includes a final commitment, the consensus rules are not applied anymore (even if still in the mining phase). This ensures that not too much space is wasted.
Every node, that receives a block, must verify that these consensus rules are followed. This means:
1. If the DKG is not in the mining phase and the new block contains a (null or non-null) commitment, the block should be rejected.
2. If no final commitment was mined for the current DKG yet and the new block does not include a (possibly null) commitment, the block should be rejected.
3. If in the current mining phase a previous block already mined a non-null commitment and the new block contains another (null or non-null) commitment, the block should be rejected.
4. If the block contains more than one commitment, the block should be rejected.
After a block with a valid (non-null) commitment has been accepted and processed, the quorum belonging to the commitment must be added to the active quorums set. From this point on, the quorum is able to perform threshold signing of arbitrary messages and all nodes in the network are able to verify the result (recovered signature) of such signing sessions.
## Activated LLMQs and threshold signing
After a DKG finishes and the final commitment has been mined, a LLMQ becomes active and can start participating in signing requests/sessions.
The details of the signing process are handled in [DIP007](https://github.com/dashpay/dips/blob/master/dip-0007.md). The individual use cases for LLMQs are handled in specialized DIPs.
## Copyright
Copyright (c) 2018 Dash Core Team. [Licensed under the MIT License](https://opensource.org/licenses/MIT)

BIN
dip-0006/aggregation.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -0,0 +1,197 @@
# BLS M-of-N Threshold Scheme and Distributed Key Generation
<pre>
Title: BLS M-of-N Threshold Scheme and Distributed Key Generation
Author(s): Alexander Block
Special-Thanks: Cofresi, Darren Tapp, Thephez, Samuel Westrich
Comments-Summary: No comments yet.
Type: Supporting Document
Created: 2018-09-07
License: MIT License
</pre>
## Abstract
This supporting document introduces a BLS based M-of-N threshold scheme. First, a simple M-of-N threshold scheme based on [Shamirs Secret Sharing](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing) is introduced. As the simple scheme requires a trusted dealer of key shares, it is unsuitable in a decentralized network. A more advanced, trustless and decentralized scheme is then introduced which removes the need for a single trusted dealer. Finally, a distributed key generation (DKG) protocol is introduced which leverages all this.
## Prior work
- [BLS Signature Scheme](bls_signature_scheme.md)
- [Secure Distributed Key Generation for Discrete-Log Based Cryptosystems](https://pdfs.semanticscholar.org/bf9e/630c13f570e2df05b6dcce3ea987015af7c3.pdf)
## Shamirs Secret Sharing
[Shamirs Secret Sharing](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing) is a known M-of-N threshold scheme that has proven to be secure if done correctly. It allows splitting a secret into a set of secret shares. A secret share does not leak any information about the original secret and thus is useless on its own. Recovery of the original secret is only possible if enough shares (m-of-n) are gathered. If someone only knows m-1 shares, he is as clueless as someone having no shares at all. The secret can be anything that is representable by a (possibly very large) number, including arbitrary binary or text data. With BLS, the secret is typically the secret key, but indirectly also the public key and signatures.
Shamirs Secret Sharing is based on polynomial evaluation and interpolation. Evaluation of the polynomials is used to create the shares and Lagrange interpolation is used to recover the original secret from m-of-n gathered secret shares. With BLS it is possible to use different types of polynomials where the results of evaluation and interpolation correspond to the other polynomials when built from the corresponding primitives.
### Polynomials in Shamirs Secret Sharing
Polynomials in Shamirs Secret Sharing are generally of the following form:
_f(x) =a<sub>0</sub> + a<sub>1</sub>x<sup>1</sup> + a<sub>2</sub>x<sup>2</sup> + a<sub>3</sub>x<sup>3</sup> + ... + a<sub>m-1</sub>x<sup>m-1</sup>_
The symbols _a<sub>0</sub>-a<sub>m-1</sub>..._ are the coefficients of the polynomial. The first coefficient _a<sub>0</sub>_ is also called the free coefficient and is always the value to be shared. The remaining coefficients are either randomly chosen values or derived from another polynomial (see descriptions of individual polynomial types).
The degree of the polynomials is always equal to M-1, meaning that the number of coefficients is always M (as it includes the free coefficient). As the form of the polynomial is always the same, it can be represented by a vector of coefficients [_a<sub>0</sub>, a<sub>1</sub>, a<sub>2</sub>, a<sub>3</sub>, ... ,a<sub>m-1</sub>_]
In the schemes described in this document, the coefficients are all either BLS secret keys, BLS public keys or BLS signatures.
_x_ is the parameter to the polynomial used when evaluating it. It is generally a value that identifies the receiver of a share and can for example be a simple (1-based) index or a hash. We will also refer to _x_ as being the “id” or “BLS Id”. Please note that _f(0)_ always evaluates to the same value as the free coefficient and thus the shared value.
### Recovery of _f(x)_ with Lagrange Interpolation
The result of the evaluation of _f(x)_ gives the _y_ coordinate of a point on the polynomial. This means, that _(x, y = f(x))_ defines a single point on the polynomial. To reconstruct the original polynomial of degree M-1, only M points on the polynomial are required if lagrange interpolation is used.
Given M shares, represented as points
_(x<sub>0</sub>, y<sub>0</sub>), (x<sub>1</sub>, y<sub>1</sub>), ..., (x<sub>m-1</sub>, y<sub>m-1</sub>)_
we can build M Lagrange base polynomials of the following form
![Lagrange base polynomial](lagrange_base_polynomial.png)
Using these Lagrange base polynomials, we can reconstruct f(x)
![Lagrange recovery](lagrange_recovery.png)
As we are only interested in the result of _f(0)_, which is identical to the free coefficient of f(x) and thus the shared value which we want to recover, the calculation can be reduced to
![f(0) Lagrange recovery](lagrange_recovery2.png)
### Secret Polynomial: _S(x)_
In the basic form of Shamirs Secret Sharing, a single polynomial _S(x)_ of degree m-1 is created. The free coefficient in this polynomial is the original secret key while the remaining m-1 coefficients are some randomly generated secret keys.
Evaluating this polynomial for each member gives the secret key share for each member. If anyone knows m of these secret shares, Lagrange interpolation can be used to recover the original secret key. If less than m secret shares are known, recovery is not possible. Due to the properties (correlation, uniqueness and determinism) of BLS, the recovered secret key will always be the same, independent from which M shares out of N were used.
The secret polynomial _S(x)_ should never be shared in public. Whoever knows _S(x)_, is able to calculate all secret key shares. Even worse, as the free coefficient is identical to the actual secret, the secret itself would be leaked.
### Public Polynomial: _P(x)_
With BLS, it is also possible to create a polynomial _P(x)_ of the same degree as _S(x)_ with all coefficients set to the corresponding public keys of _S(x)_. Evaluation of _P(x)_ gives the public keys which correspond to the secret key shares created from _S(x)_. This works due to the properties (correlation) of BLS primitives, where the same operations performed on two corresponding BLS primitives (e.g. secret and public key) will result in a new tuple of corresponding BLS primitives.
This polynomial _P(x)_ can be publicly shared and does not leak any information about the secret key. It can be used to verify that a received secret key share is actually the result of the evaluation of the polynomial _S(x)_ without knowing the polynomial. This is done by evaluating the polynomial _P(x)_ with x being the id of the sending member. The secret key share is only considered valid if the result is equal to the public key calculated from the received secret key share.
As previously described, the free coefficient of _S(x)_ is the original secret key, which also means that the free coefficient of _P(x)_ is the public key that corresponds to the original secret key. Due to the properties of BLS (correlation), this also means that a signature recovered later can be verified against this public key.
The coefficients of _P(x)_ are also called the verification vector, which well refer to when describing the distributed key generation protocol.
### Signature Polynomial: _SigP(x)_
This polynomial is actually never created and only exists in theory. It consists of the signatures which would be created if the coefficients of _S(x)_ were used to sign the same message. If this polynomial existed, evaluation of it would result in the signature shares. These signature shares would be identical to the signature shares created with the result (secret key shares) of the evaluation of _S(x)_.
Even though this polynomial is never created, the known correlation between the secret key shares and the signature shares can be used to recover a final signature by performing Lagrange interpolation on m-of-n signature shares. The resulting recovered signature validates against the free coefficient of _P(x)_. This also means, that the recovered signature is identical to the signature that would be created if the free coefficient (the original secret key) of _S(x)_ were used to sign the same message.
### (Lack of) Trust in Shamirs Secret Sharing
The BLS-based Shamirs Secret Sharing Scheme described above has a serious disadvantage when used on its own. It requires a central dealer which creates the original secret key and distributes the secret key shares and the verification vector (public polynomial) to all other members. Each member is able to verify correctness of the received secret key share by using the verification vector, but this does not protect against compromised dealers. The biggest risk with a central dealer is the risk of leaked keys, which would not be acceptable in a decentralized and trustless network.
## Aggregated Shamirs Secret Sharing
The solution to the above problem is to use an aggregated form of Shamirs Secret Sharing.
### Correlation and aggregation of polynomials
As each described polynomial type correlates to the other polynomial types, it also means that if two different polynomials of the same type are aggregated, the resulting polynomial also correlates to the aggregated polynomials of the other polynomial types. For example, if _S<sub>0</sub>(x)_ and _S<sub>1</sub>(x)_ are aggregated, the resulting polynomial _S<sub>a</sub>(x)_ correlates to _P<sub>a</sub>(x)_, which is the aggregation of the corresponding _P<sub>0</sub>(x)_ and _P<sub>1</sub>(x)_ polynomials.
It also means that the aggregation of the individual secret shares created from _S<sub>0</sub>(x)_ and _S<sub>1</sub>(x)_ with the same _x_ value would correlate to the evaluated public key shares of the aggregated _P<sub>a</sub>(x)_ with the same _x_ value.
Aggregation of two polynomials is performed by aggregating the individual coefficients of two polynomials. For example, given two polynomials represented by the coefficient vectors [a<sub>0</sub>, a<sub>1</sub>, a<sub>2</sub>] and [b<sub>0</sub>, b<sub>1</sub>, b<sub>2</sub>], the aggregated coefficients vector would be [a<sub>0</sub>+b<sub>0</sub>, a<sub>1</sub>+b<sub>1</sub>, a<sub>2</sub>+b<sub>2</sub>].
### Removing the central dealer
With the previously described properties, it is possible to remove the central dealer and instead turn every member of a threshold group into a dealer. Instead of trusting the individual dealers, the results from the individual dealers are aggregated into a single result. This in turn removes the ability of the dealers to control the outcome. It also removes the risk of leaked secrets, as leaking the secrets of individual members/dealers does not allow recovery of the actual secret.
Each dealer will create a secret key share (the contribution) from its own secret polynomial _S(x)_ for every member and share it secretly with the other individual members. Each dealer will also publicly share the public polynomial _P(x)_. After a member has received the shares from all other members, it can aggregate the shares into a new secret share.
The resulting secret share is identical to the evaluation of _S<sub>a</sub>(x)_, which is the aggregation of all members _S(x)_. However, as the polynomials _S(x)_ are never publicly shared, no one will ever know _S<sub>a</sub>(x)_ and thus will not be able to calculate the shares of other members.
Since each members public polynomial _P(x)_ is publicly known, _P<sub>a</sub>(x)_ can be created by simply aggregating them. _P<sub>a</sub>(x)_ can then be used to verify that the locally aggregated secret share is valid, simply by comparing the evaluation of _P<sub>a</sub>(x)_ with the public key calculated from the aggregated secret key share.
The aggregated secret key shares can then be used to sign messages and thus create signature shares. The resulting signature shares can be verified with the result of the evaluation of _P<sub>a</sub>(x)_, where x is the id of the signing member.
If enough signature shares are collected, Lagrange interpolation can be used to recover a final signature. Due to the properties of BLS (correlation), this signature will validate against the free coefficient of _P<sub>a</sub>(x)_, which is the threshold groups public key and corresponds to the free coefficient of the unknown polynomial _S<sub>a</sub>(x)_.
## Distributed Key Generation (DKG) Protocol
The previously described scheme assumes that every member of the threshold group is honest. However, this cant be a assumed in a decentralized and trustless network. Individual members can lie to other members or completely omit contributions. This can happen due to bugs, network problems, members being offline or malicious intents.
The solution to this is to use a Distributed Key Generation (DKG) Protocol. The protocol consists of multiple phases with messages being exchanged in each phase.
Even though the described protocol is a network protocol, we will not describe the internals of network messages and communication in this document. This is described in a specialized DIP.
The protocol consists of the following phases.
### Initialization
A few things must be verified before the actual DKG session can start. All the parameters of the DKG, for example M and N, must be agreed on. The members of the DKG session must also be deterministic, meaning that all members must use the same members list. Also, each member must have a publicly known and verified unique ID and a publicly known and verified public key usable for signing of individual messages and encryption of contributions.
### Contribution
Every member creates his own secret polynomial _S(x)_ and derives the public polynomial _P(x)_ from it. The public polynomial (verification vector) is published to all other members. The secret polynomial _S(x)_ is used to create a secret key share (the secret key contribution) for every threshold group member. These secret key contributions are then encrypted for each individual corresponding threshold group member and distributed to those members.
While generating the contributions, each member must also create a contribution for themselves.
### Complaining
After the contribution phase has finished, each member should have received one verification vector and one encrypted secret key contribution from each member. Each member should then verify all received secret key contributions by evaluating the public polynomial _P(x)_ and comparing the result with the calculated public key of the received secret key contribution.
If encryption or verification fails, the corresponding member has to be complained about. This is done by publishing a message to all other members which indicates the complaint.
The reason it is necessary to complain about members is that only a single member in the threshold group is able to verify an individual secret key contribution. This is because the contributions are encrypted individually for each member. If a member receives an invalid contribution, it must signal this to all other members, as otherwise the other members would not notice the misbehaviour.
If a member did not send any contribution at all, it must be marked as bad and is thus not considered as a valid member anymore.
### Justification
After the complaining phase has finished, each member should check if another member has complained about it. In this case, the member must publish a justification. The justification contains the unencrypted secret key contribution that was initially sent to the complaining member.
Publishing unencrypted secret key contributions here does not introduce new security risks. To understand this, we must look at the three possible scenarios:
1. Individual members get complained about. In this scenario, the revealed secret key contributions are not useful on their own, as the final secret key share is the aggregation of all contributions.
2. Every member complains about a single member. In this scenario, the member that is complained about will reveal all secret key contributions he generated for every other member. These secret key contributions are not useful as long as not all other contributions are revealed. This is because the final secret key share is the aggregation of all these secret key contributions.
3. A single member complains about all other members. In this scenario, all members will reveal the secret key contributions for this single member. These contributions can theoretically be used to calculate the final secret key share of the member. However, if a member plans to reveal his final secret key share, its more effective to just reveal it after the commitment phase. Also, a single publicly known secret key share is useless on its own as there are m-of-n secret key shares required to create a recovered signature.
### Commitment
After the justification phase has finished, each member should first check if all complaints have been resolved by valid justifications. This is done by performing the same verification as in the contribution phase, but with the unencrypted contributions of the justifying members. If a complaint has not been resolved, the member that was complained about must be marked as bad and is thus not considered as a valid member anymore.
All verification vectors of all valid members must then be aggregated into a single verification vector. This is the threshold groups public verification vector and the free coefficient is the threshold groups public key.
Also, all secret key contributions of all valid members must be aggregated into a single secret key share. This is the members final secret key share and later used to threshold sign messages.
Based on the threshold groups verification vector, the threshold groups public key and the list of valid members, a premature commitment message must be created and published. The premature commitment message is basically a vote for the DKGs result and only if enough members (e.g. at least M) created the same commitment, a final commitment can be created.
The premature commitment is signed twice, once with the secret key corresponding to the public key of the member (already known prior to the DKG session), and once with the calculated secret key share.
### Finalization
After the commitment phase has finished, each member should collect all valid commitments from all members. Each commitment where the set of valid members, verification vector and public key is identical, should be grouped together. If a group with enough commitments (e.g. at least M) is found, a final commitment must be created from the group of premature commitments.
As previously noted, premature commitments are signed twice. While creating the final commitment, both signature types need to be combined in a different way. The first signature (the one signed with the secret key corresponding to the previously known public key) is aggregated to create the first signature for the final commitment. The second signature from all premature commitments is used to perform a threshold signature recovery. The resulting recovered signature is the second signature for the final commitment.
The aggregation of member signatures ensures that a final commitment cant be crafted by random members or non-members. The final commitment is only considered valid if it was signed by enough (e.g. at least M) members. It generally signals agreement between the majority of the threshold groups members. The recovering of a final signature from the signature shares of the premature commitments is done to validate that the DKG resulted in a valid threshold groups public key.
### Example
The following matrix demonstrates how behavior is evaluated at each phase leading up to the Commitment Phase to arrive at the list of valid members:
| Phase | Action | 1 | 2 | 3 | 4 | 5 | 6 |
|--|--|--|--|--|--|--|--|
| Contribution | Received Contribution | Yes | **No** | Yes | Yes | Yes | Yes |
| Contribution | Contribution is valid | Yes | **N/A** | Yes | No | No | No |
|||||||||
| Complaint | Mark bad | | **Yes** | | No | No | No |
| Complaint | Send complaint (invalid contribution) | | | | Yes | Yes | Yes |
|||||||||
| Justification | Receive Justification | | | | **No** | Yes | Yes |
| Justification | Justification is valid | | | | **N/A** | **No** | Yes |
| Justification | Mark bad | | | | **Yes** | **Yes** | |
|||||||||
| Commitment | Commitment List (valid members) | Member | | Member | | | Member |
## Copyright
Copyright (c) 2018 Dash Core Team. [Licensed under the MIT License](https://opensource.org/licenses/MIT)

View file

@ -0,0 +1,133 @@
# BLS Signature Scheme
<pre>
Title: BLS Signature Scheme
Author(s): Alexander Block
Special-Thanks: Cofresi, Darren Tapp, Thephez, Samuel Westrich
Comments-Summary: No comments yet.
Type: Supporting Document
Created: 2018-09-07
License: MIT License
</pre>
## Abstract
This supporting document gives an introduction into the BLS (BonehLynnShacham) signature scheme. BLS is going to be used in several DIPs and this document serves as a reference for them. This document concentrates solely on the BLS primitives and their properties. Other documents will be referenced to describe the mathematical internals of BLS.
## Short introduction to BLS
[BLS](https://en.wikipedia.org/wiki/Boneh%E2%80%93Lynn%E2%80%93Shacham) is a signature scheme which was initially proposed by Dan Boneh, Ben Lynn and Hovav Shacham. A detailed description of the scheme can be found [here](http://crypto.stanford.edu/~dabo/pubs/abstracts/aggreg.html). The scheme is to some degree comparable with ECDSA and allows to verify the authenticity of arbitrary messages (e.g. p2p messages or transactions). It however has a few properties which are unique to BLS that will be described in the next section.
## Properties of BLS
BLS has a few unique properties which will allow Dash to implement higher level functionality while keeping the overhead on the blockchain to a minimum.
### Short Signatures
BLS signatures are generally shorter than signatures from other signature schemes. However, depending on the curves used, public keys might be larger than in other schemes. This negates the space savings if the BLS signature scheme is naively used for transaction signatures. In this case, significant space savings can only be achieved by leveraging the other BLS properties.
### Aggregatable
All BLS primitives (secret keys, public keys, signatures) are aggregatable, so two primitives of the same type can be combined into a single primitive of the same type. Aggregation can be performed in any order and with no practical limit on the number of aggregated primitives. Already aggregated primitives can also be further aggregated.
### Correlation
BLS primitives which correlate to each other still correlate to each other when the same arithmetical operations are performed on each of them. This holds true for simple operations like aggregation and also for more complex operations like polynomial evaluation and interpolation.
If two secret keys are aggregated, the result is a new valid secret key. If the two corresponding public keys of the secret keys are aggregated, the result is a new public key that matches the public key of the aggregated secret key. If two signatures are aggregated which were created with the two previously aggregated secret keys and the same message hash, the new signature would also validate against the aggregated public key.
![](aggregation.png)
### Uniqueness and determinism
BLS signatures are unique and deterministic. For any given public key and message combination, there can only be one valid signature. Its not possible to have two different signatures that validate against the same public key and message. This is very different than ECDSA, where the use of randomness inside the signature results in multiple possible signatures for the same public key and message.
This has a few positive effects when hashing other messages which contain a BLS signature. Such a message (e.g. a Dash or Bitcoin transaction) will always result in the same hash and its impossible to modify a signature so that the message remains valid while producing a different hash.
These properties also hold true in combination with the correlation property. If, for example, signatures are created with a threshold scheme, the resulting signature will also be deterministic and unique independent of the subset of signature shares used as input.
## BLS Primitives
The following primitives are available in the BLS signature scheme.
### Secret Key
Comparable to secret keys in ECDSA and other signature schemes. It must be kept secret and is used to create signatures.
Multiple secret keys can be aggregated to create a new secret key. If a signature is created with an aggregated secret key, the resulting signature validates against the aggregate of the public keys derived from the input secret keys. The public key of an aggregated secret key matches the aggregate of the public keys derived from the input secret keys.
### Public Key
Comparable to public keys in ECDSA and other signature schemes. It can be derived from a secret key. It is used to validate a signature together with the corresponding message hash.
Multiple public keys can be aggregated into a single public key. Such an aggregated public key validates against aggregated signatures created with the corresponding private keys.
### Signature
Comparable to signatures in ECDSA and other signature schemes, with the difference that it does not involve randomness, making the signature deterministic and unique.
Multiple signatures can be aggregated into a single signature. If all input signatures were created with the same message hash, the aggregated signature will validate against the aggregated public key of the secret keys used to used to produce the individual input signatures. If different hashes were used, aggregated verification is required.
### Message Hash
The message hash is what is actually signed with a secret key. It is highly advised to include the public key when calculating the message hash and this will be enforced through Dashs internal wrappers around the external BLS libraries. See “Rogue Public Key Attacks” for more details.
### Id
The Id is just a number and can by anything to identify an entity. It can, for example, be the index into a list or the hash of some object (e.g. ProTxId).
The Id is used in the polynomial functions of Shamirs Secret Sharing scheme. It is the “x” parameter of the evaluated polynomial.
## BLS Operations
The following operations are possible in the BLS signature scheme. Inside Dash, these are implemented as part of the wrappers around the external BLS libraries.
### Sign(secretKey, messageHash, publicKey)
Creates a signature using the secret key and Hash(messageHash, publicKey). Hashing the concatenation of the messageHash and the public key is done to ensure uniqueness of the actually signed message and serves as a protection against the rogue public key attack.
### Verify(sig, messageHash, publicKey)
Verifies the given signature against the public key and Hash(messageHash, publicKey)..
### VerifyAggregated(aggregatedSig, messageHashes, publicKeys)
Verifies the given aggregated signature against the given message hashes and public keys. Each entry in the messageHashes list must correspond to the entry at the same position in the publicKeys list.
### Aggregate(a, b)
Aggregates two BLS primitives. This is possible with secret keys, public keys and signatures.
Aggregation is an operation with associative property, meaning that the order in which aggregation happens is not important.
## Rogue Public Key Attacks
BLS Public Keys which are published in an untrusted way pose the risk of Rogue Public Key Attacks. This requires an attacker to publish a crafted public key targeted at a specific user. This public key can then later be used to create a signature which validates against the aggregate of the rogue public key and the targeted users public key. This is described in more detail in [BLS Multi-Signatures With Public-Key Aggregation](https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html).
As a defense, its generally advised to either require a proof of possession (the public key signed with the secret key) or to make all messages distinct (e.g. by including the public key in the message hash).
We chose to enforce distinct messages when signing with a secret key. Dashs internal wrappers around the external BLS libraries will require providing the public key which is used to ensure uniqueness of signed messages. Please refer to the “Sign” operation in the previous section for details.
## BLS Curves used
The BLS signature scheme requires pairing-friendly curves to be used. Multiple curves with different security, performance and space characteristics have been proposed by different parties. At the time this document was written, no decision had been made as to which curve would be used.
However, the choice of the specific curve should have no influence on the scheme itself, how BLS is used or what is possible.
This document will be updated when a decision has been made on which curve to use.
## Serialization format of BLS primitives
It is necessary to serialize BLS primitives into a byte representation so that they can be used inside other serialized data structures. How this is performed depends on the curves and libraries used. This has not been defined yet and this document will be updated later.
Until then, all DIPs will use placeholders types for the BLS primitives and assume a fixed size. These placeholder type are:
| Type | Size | Description |
| -- | -- | -- |
| BLSSecKey | 32 | BLS secret key
| BLSPubKey |64 | BLS public key
| BLSSig |32 | BLS signature
## Copyright
Copyright (c) 2018 Dash Core Team. [Licensed under the MIT License](https://opensource.org/licenses/MIT)

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

171
dip-0007.md Normal file
View file

@ -0,0 +1,171 @@
# DIP0007 -- LLMQ Signing Requests / Sessions
<pre>
DIP: 0007
Title: LLMQ Signing Requests / Sessions
Author(s): Alexander Block
Special-Thanks: Cofresi, Darren Tapp, Thephez, Samuel Westrich
Comments-Summary: No comments yet.
Status: Proposed
Type: Standard
Created: 2018-09-07
License: MIT License
</pre>
## Table of Contents
1. [Abstract](#abstract)
1. [Motivation](#motivation)
1. [Prior Work](#prior-work)
1. [Signing request](#signing-request)
1. [Signing session](#signing-session)
1. [Choosing the active LLMQ to perform signing](#choosing-the-active-llmq-to-perform-signing)
1. [Validating recovered threshold signatures](#validating-recovered-threshold-signatures)
1. [Propagating signature shares](#propagating-signature-shares)
1. [Recovered threshold signatures](#recovered-threshold-signatures)
1. [Internal high-level API](#internal-high-level-api)
1. [Copyright](#copyright)
## Abstract
This DIP defines how signing requests and sessions are performed by activated [DIP006 Long Living Masternode Quorums (LLMQs)](https://github.com/dashpay/dips/blob/master/dip-0006.md). A LLMQ is able to perform BLS threshold signing on arbitrary messages. If enough members have signed the same message, a valid recovered threshold signature can be created and propagated to the rest of the network. A successfully recovered threshold signature is strongly secure, as it is either created or not created with no in-between state that might result in different nodes seeing different/conflicting signing results.
## Motivation
We want to have a generalized method of signing arbitrary messages, which can be applied to all kinds of use cases. One use case is InstantSend, other use cases will come from new features in Evolution. We will only slightly handle InstantSend as an example in this DIP, more details can be found in the appropriate specialized DIPs.
All these use cases require unambiguous results from a signing request: It should either succeed or fail network-wide. It should not be possible to have two nodes in the network see conflicting messages with different valid signatures for the same request.
## Prior work
- [DIP 006: Long Living Masternode Quorums](https://github.com/dashpay/dips/blob/master/dip-0006.md)
## Signing request
A signing request is identified by a deterministically calculable, unique id which we will refer to as requestId in the remainder of the document. It can, for example, be the hash of an InstantSend transactions input.
Initiation of a signing request happens independently per LLMQ member. When and how to initiate the request depends on the use case. For InstantSend, this would be directly after receiving and validating a transaction.
The message hash must be supplied along with the requestId. For InstantSend, the message hash would be the hash of the full transaction. The combination of quorumHash, requestId and message hash forms the signing session.
A signing request can only be initiated once and should never be performed multiple times by the same masternode. This in turn results in “one vote per member” on each individual signing request and makes it impossible to have conflicting recovered signatures for the same signing request.
As a result of a (non-conflicting) signing request, the member must create a threshold signature share. It does this by calculating `hash(quorumHash, requestId, messageHash)` and then signing the resulting hash with the members individual threshold secret key share. After signing, the signature share must be propagated to all LLMQ members (explained later).
## Signing session
A signing session is identified by the LLMQs quorumHash, signing request id and the message hash. If any member of the LLMQ receives enough threshold signature shares for a signing session, it can create the final recovered threshold signature from these shares. This recovered signature is propagated to the whole network (including non-members) and can then be verified by all nodes based on the LLMQs quorum public key.
If different members signed the same request with differing message hashes, only one of the signing sessions will create enough signature shares to reach the threshold and thus only one valid recovered signature can be created. If not enough signature shares for the same signing session can be collected, no valid recovered threshold signature will be created. In the InstantSend use case, this would indicate a failed attempt to double spend transaction inputs.
## Choosing the active LLMQ to perform signing
As multiple LLMQs might be active at the same time and masternodes might be members of multiple LLMQs as well, its important that all masternodes agree on which LLMQ should service the signing request. Otherwise it would be impossible to collect enough signature shares for the same signing session and thus recovery of the threshold signature would never succeed.
To calculate which LLMQ is responsible for a signing request, each masternode should perform the following:
1. Take the last `X` activated LLMQs. The value of `X` depends on the use case, and could be 4 as an example.
2. For each LLMQ, calculate `hash(quorumHash, requestId)`
3. Sort the list of LLMQs based on the result of step 2 in ascending order.
4. Use the first entry of the sorted list as the LLMQ to perform the signing request
After the responsible LLMQ is determined, the masternode should check if it is part of the chosen LLMQ. If it is not part of that LLMQ, it must completely skip the signing request.
## Validating recovered threshold signatures
Each node (including regular nodes) must verify the recovered signatures for each signing session before accepting and relaying them. This can be done by validating the recovered signature and `hash(quorumHash, requestId, messageHash)` against the LLMQs quorum public key.
If this succeeds, the signing request is considered successful. In the InstantSend example, this would mean that a single input of the transaction has been locked.
## Propagating signature shares
Propagation of signature shares is performed through the Intra-Quorum Communication mechanism described in [DIP006](https://github.com/dashpay/dips/blob/master/dip-0006.md). This means, that only the members of a LLMQ see and propagate signature shares belonging to this LLMQ. Watchers that connect and issue the `qwatch` message will also receive signature shares.
Propagation of signature shares however does NOT use the inventory system of Dash. Instead, signature shares are sent to other quorum members in a batched message. This is due to the overhead and latency in the inventory system that, while acceptable for other message types, is unsuitable for the low-latency requirement of the signature share system. Fortunately, signature shares can be batched in a way that keeps the overhead to a minimum compared to the inventory system (and might even reduce it). The most important advantage is the removal of the latency produced by the multiple round-trip (INV->GETDATA->MESSAGE) sequences, which would add up to unacceptable latencies when propagating hundreds of messages.
When a member has signed his own signature share or validated incoming signature shares, it must add these signature shares to a pending list of batched signature shares per other member in the deterministic connections (see [DIP06, Intra-Quorum Connections](https://github.com/dashpay/dips/blob/master/dip-0006.md#intra-quorum-communication)) set. It should then periodically (e.g. every 100ms) send out all pending batches.
On receipt of a batch, each included share must be validated individually.
Validation includes:
1. The `quorumHash` must belong to an activated LLMQ
2. `shareCount` must not be larger than the `quorumSize`
3. Each entry in `shareMembers` must be in the bounds of `quorumSize`
4. No duplicate entries in `shareMembers`
5. No duplicate entries in `shareSigs`
6. The individual shares must validate to the corresponding public key shares of the corresponding members
Valid shares from the batched message must be relayed even if other shares are invalid. If an invalid share is encountered, the sending node must be banned even if other shares were valid.
If an individual share was already received from another member, verification and relaying can be skipped (as both were already done before). It is safe to check duplicate shares by hash as BLS signatures cannot differ for the same message.
The internal Dash message name is `qbsigshares` and the format of the message is:
| Field | Type | Size | Description |
|--|--|--|--|
| quorumHash | uint256 | 32 | The quorum identifier |
| id | uint256 | 32 | The signing request id |
| messageHash | uint256 | 32 | The message hash |
| shareCount | compactSize uint | 1-9 | The number of signature shares in this batch |
| shareMembers | uint32[] | 4 * shareCount | Member indexes of the shares in this batch |
| shareSigs | BLSSig[] | 32 * shareCount | The signature shares |
### Recovered threshold signatures
After a member of a LLMQ has received enough (`>= quorumThreshold`) shares for a signing session, it can create the final recovered threshold signature from the signature shares. If this succeeds, the recovered threshold signature must be relayed to the whole network (including non-members).
If a valid recovered threshold signature was already received before enough shares have been received, recovering can be skipped. The reason is that the custom-created recovered signature would always be identical to the received one, thanks to the uniqueness property of BLS signatures.
On receipt of a recovered signature, all nodes should perform the following verification:
1. The `quorumHash` should belong to an active LLMQ
2. The `thresholdSig` should validate against the LLMQs quorum public key and `hash(quorumHash, id, messageHash)`.
Propagation of recovered signature shares utilizes the inventory system.
The internal Dash message name is `qsigrec` and the format of the message is:
| Field | Type | Size | Description |
|--|--|--|--|
| quorumHash | uint256 | 32 | The quorum identifier |
| id | uint256 | 32 | The signing request id |
| messageHash | uint256 | 32 | The message hash |
| thresholdSig | BLSSig | 32 | The final recovered threshold signature |
## Internal high-level API
Inside the Dash Core Node, we will implement a high-level API that can be leveraged by the individual use cases. The API will support the following operations:
### void SignIfMember(uint256 id, uint256 msgHash, int activeLLMQs)
Selects the correct LLMQ based on the last active LLMQs and performs the signing request if the caller is a member and only if it did not already sign another signing session for the same signing request.
### void Sign(uint256 quorumHash, uint256 id, uint256 msgHash)
Sign the given session if the caller is a member of the given quorum.
### bool HasRecoveredSig(uint256 id, uint256 msgHash, int activeLLMQs)
Returns true if a valid recovered threshold signature was received (or locally created) for the signing session and from the last active LLMQs. Please note that the `activeLLMQs` parameter must not necessarily be the same value as was previously given to `SignIfMember`. For some use cases it might be desirable to accept signatures from old/inactive LLMQs as well.
### bool IsConflicting(uint256 id, uint256 msgHash)
Returns true if any LLMQ created a valid recovered threshold signature for any signing session with a different message hash than the given one.
### bool IsMajorityPossible(uint256 id, uint256 msgHash, int activeLLMQs)
Returns true if a recovered signature has already been received (or locally created) or if its still possible for this to happen. This means, that it returns false if `>= quorumThreshold` members have already signed a different signing session for the same request.
### uint256 GetMostSignedSession(uint256 id, int activeLLMQs)
Returns the `msgHash` which was signed by most LLMQ members so far. Please note that the result is not final until `HasRecoveredSig` returns true.
These operations will also be made available through RPC APIs so that external applications can also use the LLMQ signing capabilities. This will especially be useful for Evolution, as non-core services (L2) can then simply call these RPCs and wont have to deal with the internals.
## Copyright
Copyright (c) 2018 Dash Core Team. [Licensed under the MIT License](https://opensource.org/licenses/MIT)