Skip to content

Commit

Permalink
Merge pull request #12 from iotaledger/tip47
Browse files Browse the repository at this point in the history
TIP-47: Storage Deposit
  • Loading branch information
muXxer authored May 12, 2023
2 parents 8cd1523 + cfbe787 commit 4f67068
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
145 changes: 145 additions & 0 deletions tips/TIP-0047/tip-0047.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
tip: 47
title: Dust Protection Based on Byte Costs (Storage Deposit)
description: Prevent bloating the ledger size with dust outputs
author: Max Hase (@muXxer) <[email protected]>
discussions-to: TODO
status: Draft
type: Standards
layer: Core
created: 2023-05-12
requires: TIP-20, TIP-21, TIP-22 and TIP-38
replaces: TIP-19
---

## Summary

This document describes a `dust protection` concept, called `storage deposit` which was originally introduced in TIP-19. This cocnept creates a monetary incentive to keep the ledger state small. This is achieved by enforcing a minimum IOTA coin deposit in every output based on the actually used disc space of the output itself.

This document minimally extends on TIP-19 by allowing for additional weights to be defined in other TIPs and no longer includes the deposit calculation for each individual output. Instead, each TIP defining outputs has to include the deposit calculation.

## Motivation

In a distributed ledger network, every participant, a so-called node, needs to keep track of the current ledger state. Since `chrysalis-pt2`, the IOTA ledger state is based on the UTXO model, where every node keeps track of all the currently unspent outputs.

Misusage by honest users or intentionally bad behavior by malicious actors can lead to growing database and snapshot sizes and increasing computational costs (database lookups, balance calculations). Due to these increasing hardware requirements, the entry barrier to participate in the network becomes unaffordable and less nodes would operate the network.

Especially in a fee-less system like IOTA, this is a serious issue, since an attacker can create a lot of damage with low effort. Other DLTs do not yet face this problem, as such an attack would be much more expensive due to the high transaction fees.
However, in order to solve scalability issues more and more transactions need to be handled. Therefore, other DLT projects will also eventually run into the same dust limitations. This document proposes to introduce `storage deposit` to address this.

## Requirements

- The maximum possible ledger database size must be limited to a reasonable and manageable size.
- The `dust protection` must not depend on a global shared state of the ledger, so that transaction validation can happen in parallel.
- The `dust protection` should work for outputs with arbitrary data and size.
- The ledger database size should be fairly allocated to users based on the scarce resource, IOTA coins.

## Detailed Design

A transaction validation rule is introduced which is exactly the same as the one defined in TIP-19, but stated here again for self-containment.

Blocks including payloads, even transaction payloads, are considered to be pruned by the nodes, but unspent transaction outputs must be kept until they are spent. Therefore the `dust protection` is based on the unspent outputs only.

**Every output created by a transaction needs to have at least a minimum amount of IOTA coins deposited in the output itself, otherwise the output is syntactically invalid.**

min_deposit_of_output = ⌊v_byte_cost · v_byte⌋
v_byte = ∑(weight<sub>𝑖</sub> · byte_size<sub>𝑖</sub>) + offset

where:
- v_byte_cost: costs in IOTA coins per virtual byte
- weight<sub>𝑖</sub>: factor of field 𝑖 that takes computational and storage costs into account
- byte_size<sub>𝑖</sub>: size of field 𝑖 in bytes
- offset: additional v_bytes that are caused by additional data that has to be stored in the database but is not part of the output itself

| :warning: `min_deposit_of_output` is rounded down |
| ------------------------------------------------- |

TIP-18 and its replacement TIPs introduce new output types that contain mandatory and optional fields with variable length. Each of these fields result in different computational and storage costs, which will be considered by the positive `weight_i`. The size of the field itself is expressed with `byte_size_i`. `offset` is used to take the overhead of the specific output itself into account.

The `v_byte_cost` is a protocol value, which has to be defined based on reasonable calculations and estimates.

**In simple words, the more data you write to the global ledger database, the more IOTA you need to deposit in the output.**
This is not a fee, because the deposited coins can be reclaimed by consuming the output in a new transaction.

### How does it affect other parts of the protocol?

The `dust protection` only affects "value-transactions". Since blocks containing other payloads are not stored in the ledger state and are subject to pruning, they cannot cause permanent "dust" and do not need to be considered for `dust protection`.
However, all output types like e.g. smart contract requests are affected and must comply with the `min_deposit_of_output` criteria. Therefore, these requests could get quite expensive for the user, but the same mechanism introduced for [Microtransactions on Layer 1](#Microtransactions-on-Layer-1) can be utilized for smart contract requests as well.

### Byte cost calculations

To limit the maximum database size, the total IOTA supply needs to be divided by the target database size in bytes to get the worst case scenario regarding the byte costs.

However, in this scenario no outputs hold more IOTA coins than required for the `dust protection`. This does not represent the real distribution of funds over the UTXOs. We could assume that these output amounts follow Zipf's law. Unfortunately, fitting a Zipf distribution to the current ledger state will not match the future distribution of the funds for several reasons:

- There is already another `dust protection` in place, which distorts the distribution.
- With new use cases enabled by the new `dust protection` (e.g. tokenization, storing arbitrary data in the ledger), the distribution will dramatically change.
- Fittings for other DLT projects do not match because there are transaction fees in place, which decrease the amount of dust outputs in the distribution.

Another possibility would be to estimate how much percentage of the database will be used for outputs with minimum required deposit (`fund sparsitiy percentage`) in the future. The remaining IOTA coins can be ignored in that case to simplify the calculation. Since a fund sparsity percentage of less than 20% would already be bad for other upcoming protocol features like the mana calculation, we could take this value for our calculation instead of the worst case.

### Weights for different outputs

Output types contain several mandatory and optional fields. Every field itself creates individual computational and storage requirements for the node, which is considered by having different weights for every field.

##### Field types

The following table describes different field types in an output:

<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Weight</th>
<th>Reasoning</th>
</tr>
<tr>
<td><code>key</code></td>
<td>Creates a key lookup in the database.</td>
<td>10.0</td>
<td>Keys need to be stored in the LSM tree of the key-value database engine and need to be merged and leveled, which is computational-, memory- and read/write IO-wise a heavy task.</td>
</tr>
<tr>
<td><code>data</code></td>
<td>Plain binary data on disk.</td>
<td>1.0</td>
<td>Data is stored as the value in the key-value database, and therefore only consumes disc space.</td>
</tr>
</table>

TIPs that define new output types may define additional weights based on the storage and computational requirements that the affected fields induce for the node. However, the weights defined here should take precedence whenever possible and inform the newly defined weights.

| :warning: Protocol parameters are not set yet |
| ---------------------------------------------- |

Protocol parameters presented in this document are design parameters that will change in the future based on simulation results, benchmarking and security assumptions. The reader should not take these values as definitive.

An example of such parameter for example is the `weight` assigned to different output field types.

### Microtransactions

#### Microtransactions on Layer 1

To enable microtransactions on Layer 1 and still satisfy the `min_deposit_of_output` requirement, a new mechanism called `conditional sending` is introduced with [TIP-38](../TIP-0038/tip-0038.md).

![Microtransactions on Layer 1](assets/microtransactions_pt3_layer1.png)

The preceding picture shows the process of the `conditional sending` mechanism. Alice uses the `Basic Output` ([TIP-41](../TIP-0041/tip-0041.md)) to send a microtransaction of 1 IOTA to Bob's `Address`. To fulfill the `min_deposit_of_output` requirement, the `Amount` is increased by `min_deposit_of_output` IOTA, which is 1 MIOTA in the above example. To prevent Bob from accessing these additional funds called the `storage deposit`, Alice adds the optional `Storage Deposit Return Unlock Condition` to the `Basic Output`. Now Bob can only consume the newly created output, if the unlocking transaction deposits the specified `Return Amount` IOTA coins, in this case 1 MIOTA, to the `Return Address` value defined by Alice. By consuming another UTXO and adding its amount to the received 1 IOTA, Bob takes care to create a valid output according to the dust protection rules.

To prevent Bob from blocking access to the `storage deposit` forever, Alice specifies the additional `Expiration Unlock Condition` in the `Basic Output`. If Bob does not consume the output before the time window defined by Alice expires, Alice regains total control over the output.

This means that there is no risk for Alice to lose the `storage deposit`, because either Bob needs to return the specified `Return Amount`, or the ownership of the created output switches back to Alice after the specified time-window has expired.

This mechanism can also be used to transfer native tokens or on-chain requests to ISCP chains without losing control over the required `storage deposit`.

#### Microtransactions on Layer 2

Another solution is to outsource microtransactions to Layer 2 applications like smart contracts. In Layer 2 there are no restrictions regarding the minimum balance of an output.

![Microtransactions on Layer 2](assets/microtransactions_pt3_layer2.png)

In this example, Alice sends funds to a smart contract chain on Layer 1 with an output that covers at least `min_deposit_of_output`. From this point on, Alice can send any number of off-chain requests to the smart contract chain, causing the smart contract to send microtransactions from Alice' on-chain account to Bob's on-chain account. Bob can now request his on-chain account balances to be withdrawn to his Layer 1 address. The last step can also be combined with the formerly introduced `conditional sending` mechanism, in case Bob wants to withdraw less than `min_deposit_of_output` IOTA coins or native assets.

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

0 comments on commit 4f67068

Please sign in to comment.