# 10 - LLMQ InstantSend
  DIP: 0010
  Title: LLMQ InstantSend
  Author(s): Alexander Block
  Special-Thanks:
  Status: Final
  Type: Standard
  Created: 2019-05-16
  License: MIT License
## Table of Contents 1. [Abstract](#abstract) 1. [Motivation](#motivation) 1. [Prior Work](#prior-work) 1. [Making all transactions instant](#making-all-transactions-instant) 1. [Used LLMQ type](#used-llmq-type) 1. [Eligible transactions for InstantSend](#eligible-transactions-for-instantsend) 1. [Locking Transaction Inputs](#locking-transaction-inputs) 1. [Finalization and creation of ISLOCK messages](#finalization-and-creation-of-islock-messages) 1. [Detecting and handling double-spend attempts](#detecting-and-handling-double-spend-attempts) 1. [Conflicts between ChainLocks and InstantSend](#conflicts-between-chainlocks-and-instantsend) 1. [Retroactive signing of transactions in blocks](#retroactive-signing-of-transactions-in-blocks) 1. [Dangling Partial Locks](#dangling-partial-locks) 1. [Persistence of InstantSend locks](#persistence-of-instantsend-locks) 1. [Copyright](#copyright) ## Abstract This DIP defines a new implementation for InstantSend based on DIP0006 LLMQs and DIP0007 LLMQ Signing Requests/Sessions. ## Motivation InstantSend is a feature to allow instant confirmations of payments. It works by locking transaction inputs through masternode quorums. It has been present in Dash for a few years and been proven to work. Nevertheless, there are some limitations which could theoretically be fixed in the old system. However, fixing these limits in the old system (i.e. before LLMQs) would have created risks in terms of scalability and security. With LLMQs, these limitations can be lifted to enable more scaling and a better user experience. ## Prior work * [DIP 0006: Long Living Masternode Quorums](https://github.com/dashpay/dips/blob/master/dip-0006.md) * [DIP 0007: LLMQ Signing Requests / Sessions](https://github.com/dashpay/dips/blob/master/dip-0007.md) * [DIP 0008: LLMQ based ChainLocks](https://github.com/dashpay/dips/blob/master/dip-0008.md) * [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) ## Making all transactions instant LLMQ-based InstantSend allows all transactions to be treated as InstantSend transactions. The old system differentiated transactions as InstantSend transactions by using the P2P message `ix` instead of `tx`. In the new system, such distinction is not required anymore as LLMQs will try to lock every valid transaction by default. If `ix` P2P messages are received from older clients, nodes should convert these to simple `tx` messages and treat them as such (including processing and propagating as `tx`). ## Used LLMQ type All signing sessions/requests involved in InstantSend must use the LLMQ_50_60 LLMQ type. ## Eligible transactions for InstantSend When a transaction is received and successfully added to the mempool (which means it also passes the usual validation checks), each masternode should check if the transaction is eligible for InstantSend. A transaction is eligible for InstantSend when each of its inputs is considered confirmed. This is the case when the previous transaction referred to by the input is confirmed with 6 blocks, confirmed through an older InstantSend lock or the block containing it is ChainLocked. When checking the previous transaction for an InstantSend lock, it is important to also do this on mempool (non-mined) transactions. This allows chained InstantSend locking. ## Locking Transaction Inputs When a transaction is eligible for InstantSend, each masternode should try to initiate a signing request for each of the transaction’s inputs. The request id is: ```text SHA256("inlock", prevTxHash, prevTxOut) ``` `"inlock"` is a static string, prepended with the length (6, as a compact int, which is a single byte) of the string. The message hash of the signing request is the txid/hash of the transaction to be locked. The [DIP0007 LLMQ Signing Request/Sessions](https://github.com/dashpay/dips/blob/master/dip-0007.md) subsystem should handle the signing and recovery of signatures afterwards. It will also automatically determine if the local masternode has to sign a share or if it should skip it. In case of conflicts between transactions which are not fully locked yet, the DIP0007 subsystem will handle this as well by skipping signing of conflicting inputs. Each masternode should then wait for the recovered signatures for each input to appear. When all recovered signatures have appeared, each masternode should initiate the finalization phase. ## Finalization and creation of ISLOCK messages When a masternode has observed all recovered signatures for each input of a transaction, it should initiate the finalization and creation of an `ISLOCK` message. Finalization is simply another signing request, performed on a (potentially) different LLMQ than used before. The request id of the new signing request is: ```text SHA256("islock", inputCount, prevTxHash1, prevTxOut1, prevTxHash2, prevTxOut2, ...) ``` `"islock"` is a static string, prepended with the length (6, as a compact int, which is a single byte) of the string. `inputCount` is a compact int, comparable to what is typically used in serialized arrays/vectors to serialize the size. After `inputCount`, multiple pairs of <`prevTxHash`, `prevTxOut`> follow, which are corresponding to the individual inputs of the transaction to be locked. The message hash of the signing request is the txid/hash of the transaction to be locked. The LLMQ Signing Request/Sessions subsystem will handle this the same way as in the previous section. When a masternode receives the recovered signature for this signing request, it should use the signature to create a new p2p message, which is the `ISLOCK` message. It has the following structure: | Field | Type | Size | Description | |--|--|--|--| | inputCount | compactSize uint | 1 - 9 | Number of inputs in the transaction | | inputs | COutpoint[] | `inputCount` * 36 | Inputs of the transaction. COutpoint is a uint256 (hash of previous transaction) and a uint32 (output index) | | txid | uint256 | 32 | txid/hash of the transaction | | sig | BLSSig | 96 | Recovered signature from the signing request/session | This p2p message should be propagated to all full nodes, including non-masternodes. This is done using the `INV`/`GETDATA` subsystem. It should also be propagated to SPV nodes if the transaction referred to by the txid matches the bloom filter of the SPV node. Receiving nodes should verify the message by checking the signature against the responsible LLMQ’s public key. The responsible LLMQ can be determined by re-calculating the request id from the data found in the `ISLOCK` message and then choosing the responsible LLMQ with the help of the LLMQ Signing Requests/Sessions subsystem. If the `ISLOCK` message is determined to be valid, it should be propagated further. All full nodes and SPV nodes should only consider a transaction to be locked when a valid `ISLOCK` for the transaction is available. The individual inputs previously locked and their corresponding recovered signatures should not be used when it comes to `ISLOCK` validation. ## Detecting and handling double-spend attempts When an `ISLOCK` message is present, it can be used to easily detect conflicting transactions which try to double spend the locked transaction inputs. This is even possible when the original transaction is not present and only the `ISLOCK` message is present (which might be the case due to the first-seen rule). Each time an `ISLOCK` message is received, nodes should check the mempool and recent non-ChainLocked blocks for conflicting transactions. A transaction is considered conflicting when it spends an outpoint found in the `ISLOCK` message but its txid/hash does not match the txid from the `ISLOCK` message. The same checks should be performed when a transaction is received before the corresponding (or conflicting) `ISLOCKs` are received. This includes transactions received through normal transaction propagation or through mined blocks. If a conflict is found in the mempool, the conflicting transaction should be removed from the mempool. The originally locked transaction will naturally not be present in this situation, as the first-seen rule would have already filtered it. Thus the transaction referenced in the `ISLOCK` message should be re-requested from one of the nodes that had previously announced it. If a conflict is found in a recently mined block, conflict resolution depends on the ChainLock state of the block. If the block is not ChainLocked, the whole block must be invalidated. This might result in a reorganization of the chain and re-acceptance of non-conflicting transactions in the local mempool. If the block (or one of its descendants) has a ChainLock, the `ISLOCK` (and all chained descendants) must be ignored and pruned from memory (including persistent memory). ## Conflicts between ChainLocks and InstantSend The latter case with a conflicting block receiving a ChainLock is very unlikely to happen. The ChainLocks system usually does not try to lock blocks which contain non-InstantSend locked transactions. This means that even if a miner manages to include a conflicting TX into a block, masternodes following normal consensus rules will not create a ChainLock for this block. Consequently the block would be invalidated on all nodes when the `ISLOCK` appears. Only in the case of an attack, where an attacker managed to get control over large parts of the masternode network, would this situation becomes a possibility. In this situation, ChainLocks have a higher priority when it comes to consensus. Please see [DIP0008 - ChainLocks](https://github.com/dashpay/dips/blob/master/dip-0008.md) for more details. ## Retroactive signing of transactions in blocks When a block is received that contains transactions which were previously unknown to the receiving masternode, the masternode should try to lock these transactions the same way as those received through normal transaction propagation. In most cases, this will be a no-op as the `ISLOCK` will already be present locally and thus the locking attempt can be skipped. Retroactive signing however becomes important when miners include transactions in new blocks which are not known by the remainder of the network. As it is desirable to lock all transactions, retroactive signing ensures that even these transactions get locked. Once they are InstantSend-locked, this allows the ChainLocks system to lock the most recently mined block even though it originally included non-locked transactions. ## Dangling Partial Locks In rare cases, a transaction input may not be locked. This could result in a transaction where only some of the inputs are successfully locked. This would happen if a LLMQ becomes inactive in the middle of a signing session due to a fresh LLMQ pushing an old LLMQ out of the active list. In this case, some members of the old LLMQ may not receive the transaction in a timely manner and thus do not perform the threshold signing. It might also happen if a LLMQ becomes dysfunctional, e.g. due to too many members being offline or unresponsive. In the initial implementation, we will ignore this unlikely scenario and simply consider the transaction as not locked, which also means that the `ISLOCK` message is never created. Such a transaction reverts to being a normal transaction and will be mined with a delay of a few minutes. See ["Safe Transactions” in DIP0008 - ChainLocks](https://github.com/dashpay/dips/blob/master/dip-0008.md#safe-transactions) for more details. ## Persistence of InstantSend locks An InstantSend lock should be persistent until the corresponding transaction is mined on-chain and either confirmed by 24 blocks or a ChainLock. InstantSend locks for non-mined transaction should never expire or time out. Persistency is meant to be persistent on-disk and able to survive restarts of the node. Storing InstantSend locks in RAM only is not enough. ## Copyright Copyright (c) 2019 Dash Core Group, Inc. [Licensed under the MIT License](https://opensource.org/licenses/MIT)