Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reintroduce the uniqueness requirement for transactionIDs #21

Merged
merged 2 commits into from Sep 9, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 9 additions & 9 deletions proposals/lip-0015.md
Expand Up @@ -5,13 +5,13 @@ Author: Andreas Kendziorra <andreas.kendziorra@lightcurve.io>
Discussions-To: https://research.lisk.io/t/enable-transaction-invalidation-by-using-nonces/
Type: Standards Track
Created: 2019-01-29
Updated: 2019-05-10
Updated: 2019-09-06
Requires: 0009
```

## Abstract

This LIP proposes to replace timestamps by nonces in transaction objects. No constraints on the order of nonces shall be used. Moreover, the requirement that the transactionID has to be unique is replaced by the requirement that the combination of address, nonce and network identifier has to be unique. This will allow to invalidate pending transactions by reusing the nonce while still preventing transaction replay attacks.
This LIP proposes to replace timestamps by nonces in transaction objects. No constraints on the order of nonces shall be used. Moreover, the requirement that the combination of address, nonce and network identifier has to be unique is added. This will allow to invalidate pending transactions by reusing the nonce.

## Copyright

Expand Down Expand Up @@ -45,11 +45,11 @@ As concluded in the previous subsection, restrictions on the value of the timest

### Enabling Invalidation of Transactions

As mentioned in the motivation, there is currently no way to invalidate pending transactions. Therefore, we propose to not enforce the uniqueness of transactionIDs, but rather of nonces used for an account. More precisely, the combination of address, nonce and network identifier (see LIP [0009](https://github.com/LiskHQ/lips/blob/master/proposals/lip-0009.md)) has to be unique. This prevents transaction replay attacks in the same way as unique transactionIDs do. But it also allows to invalidate pending transactions by reusing the nonce. This can be used, for example, in the case of pending low-fee transactions as mentioned above: Issuing the original transaction again with the same input, including the same nonce, but with a higher fee can replace the first transaction.
As mentioned in the motivation, there is currently no way to invalidate pending transactions. Therefore, we propose to enforce the uniqueness of nonces used for an account. More precisely, the combination of address, nonce and network identifier (see LIP [0009](https://github.com/LiskHQ/lips/blob/master/proposals/lip-0009.md)) has to be unique. This allows to invalidate pending transactions by reusing the nonce. This can be used, for example, in the case of pending low-fee transactions as mentioned above: Issuing the original transaction again with the same input, including the same nonce, but with a higher fee can replace the first transaction.

To invalidate a transaction without replacing it by a meaningful one, the sender could, for example, create a balance transfer transaction to his or herself where the nonce of the transaction that is supposed to be invalidated, is used. Once this new transaction has been included, it is guaranteed that the first transaction would not be included anymore. Of course, the original transaction may be included before the second one. In this case, the user has certainty about the original transaction (included in the blockchain) and it is guaranteed that the second one does not get included.

One may argue that enforcing uniqueness solely to the nonce value is sufficient too. That means, each nonce value would be allowed to be included in the blockchain only once. This is also prevents transaction replays and allows transaction invalidation, but increases the probability of rejected transactions due to already used nonces. This is especially the case when many users/clients tend to choose nonces not uniformly at random, for example, by choosing the operating system time as the nonce. Moreover, it allows users to invalidate pending transactions of other users.
One may argue that enforcing uniqueness solely to the nonce value is sufficient too. That means, each nonce value would be allowed to be included in the blockchain only once. This is also allows transaction invalidation, but increases the probability of rejected transactions due to already used nonces. This is especially the case when many users/clients tend to choose nonces not uniformly at random, for example, by choosing the operating system time as the nonce. Moreover, it allows users to invalidate pending transactions of other users.

Alternatively, one could also enforce the uniqueness of the combination of address and nonce. But this does not allow to delete the used combinations every time the network identifier changes. When enforcing the uniqueness of the combination of address, nonce and network identifier, all used combinations can be deleted when the network identifier changes. This is because transactions using the old network identifier are invalid and there is no need to check if the combination of address, nonce and network identifier was already used. See also the section [Impact on Storage and Performance](#Impact-on-Storage-and-Performance) for more reasoning why this is advantageous.

Expand Down Expand Up @@ -79,11 +79,15 @@ An average PC should be able to perform a few thousand queries per second for co

The impact on storage and performance will not be drastic in the near future because several hard forks are planned which every time results in a change of the network identifier. Hence, the previously used combinations can always be deleted. Once there is a long period without a hard fork, the impact on storage and performance could have a significant impact. In the [appendix](#Possibilities-to-Mitigate-the-Impact-on-Storage-and-Performance), some possibilities that could mitigate the impact are mentioned. This is, however, no complete research and no solution shall be specified in this LIP. If mitigation solutions are desired in the future, the solution shall be implemented in a separate step.

### Uniqueness of transactionIDs

One purpose of the uniqueness requirement for transactionIDs in the current protocol is the prevention of transaction replay attacks. Due to the uniqueness requirement for the combination of address, nonce and network identifier added in this proposal, one could drop the uniqueness requirement for transactionIDs without adding any risk for transaction replay attacks. However, transactionIDs are also used to uniquely identify transactions, for instance, in RPCs, the API of Lisk Core and frontend tools like Lisk Hub. Therefore, we keep the uniqueness requirement.

### Discarded Alternatives

#### Unspent Transaction Outputs

Unspent transaction outputs (UTXOs) as used in Bitcoin make it very easy to invalidate transactions: If the transaction `tx` should be invalidated, one simply has to reuse one UTXO used in `tx` in a new transaction. At the same time, transaction replay attacks get prevented because a UTXO cannot be spent twice. Using UTXOs in Lisk would, however, require drastic changes of the protocol and implementation. Therefore, UTXOs were disregarded.
Unspent transaction outputs (UTXOs) as used in Bitcoin make it very easy to invalidate transactions: If the transaction `tx` should be invalidated, one simply has to reuse one UTXO used in `tx` in a new transaction. Using UTXOs in Lisk would, however, require drastic changes of the protocol and implementation. Therefore, UTXOs were disregarded.

#### Invalidation Transaction

Expand Down Expand Up @@ -111,10 +115,6 @@ Every transaction object needs a `nonce` property. The value of this property ha

was not used for any other transaction included in the blockchain before. If this combination was already used, the transaction has to be rejected. Note that the network identifier is not part of the transaction JSON object. It is only part of the input message of the transaction signature, and a signature is rejected if the message did not contain the correct network identifier (see LIP [0009](https://github.com/LiskHQ/lips/blob/master/proposals/lip-0009.md) for more details).

#### TransactionID

The uniqueness of transactionIDs shall be dropped. That means, a transaction is not considered to be invalid just because there exists already another transaction in the blockchain with the same transactionID.

### Serialization for Signature and TransactionID Generation

In the serialization process for creating a byte array that serves as the input for SHA-256 whose output in turn is used as the input message for EdDSA, the `nonce` value follows the `type` value and gets followed by the `senderPublicKey` value. The nonce value uses 64 bits and shall be encoded big endian.
Expand Down