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

TIP-37 Dynamic PoW #81

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions tips/TIP-0037/tip-0037.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
tip: 37
title: Dynamic PoW
description: Dynamically adapt the PoW difficulty
author: Luigi Vigneri (@vekkiokonio) <luigi.vigneri@iota.org>, Wolfgang Welz (@Wollac) <wolfgang.welz@iota.org>
discussions-to: https://github.com/iotaledger/tips/discussions/81
status: Draft
type: Standards
layer: Core
created: 2022-05-31
---

# Abstract

The IOTA protocol uses proof-of-work as a means to rate-limit the network (see [TIP-12](../TIP-0012/tip-0012.md)). Currently, the required difficulty for blocks to be considered valid is set to the constant `Min PoW Score`. This document proposes a way for the network coordinator to dynamically change the PoW difficulty to be able to adjust more efficiently to the current network conditions.

# Motivation

Any constant `Min PoW Score` always needs to make a trade-off between usability for small devices like Raspberry Pi and protecting the network from a spam attack where several very powerful machines completely spam the network so that all but the most powerful nodes would lose sync. Thus, especially for time periods in which the network is completely underused, such a constant score inevitably leads to too high difficulties hindering network usage and adoption.
Adjusting the PoW score dynamically can provide the best of both worlds by raising the difficulty to protect the network under attack or peak usage or by lowering the difficulty in all other cases.

This document proposes to add a config option to every milestone that allows the coordinator to change the PoW difficulty. Based on this, we would like to design a congestion control algorithm with the following features:
- Deterministic in order to guarantee consistency.
- Depends on the past cone of a given milestone.

# Specification

Changes of the PoW difficulty are announced in a milestone. This is part of the _Protocol Parameters Milestone Option_ as defined in [TIP-29](../TIP-0029/tip-0029.md). The following parameters are encoded into the `Parameters` field of the option:

| Name | Type | Description |
| -------------- | ------ | ------------------------------------------------ |
| Next PoW Score | uint32 | The new PoW score all blocks should adhere to. |


### Option syntactic validation

- `Target Milestone Index` of the _Protocol Parameters Milestone Option_:
- Must be greater than `Index Number` of the encapsulating milestone
- Must not be larger than `Index Number` plus `Max Activation Period`, which bounds how far in the future the new PoW score can be activated.

The `Max Activation Period` parameter plays an important role in this proposal: on the one hand, we want to set it reasonably small to store less information in the snapshot file used for node bootstrapping; on the other hand, it cannot be smaller than the expected milestone delivery delay, i.e. in this proposal we assume that milestones are received by all nodes within `Max Activation Period`. As a proposal, we could set `Target Milestone Index` not to be larger than `Index Number` plus `Below Max Depth`.

### Changes in block validation

The `Next PoW Score` field in a _Protocol Parameters Milestone Option_ influences what blocks are accepted by a node. This depends on the current PoW score. The PoW score announced for `Target Milestone Index` becomes active in a node as soon as a valid milestone with that particular `Index Number` is received:
- Blocks that are received via gossip that do not match that PoW score will be discarded, i.e. they are not gossiped and not included in the Tangle.
- The PoW of blocks that are in the past cone of a valid milestone is not checked. This assures that PoW score changes cannot break syncing or bootstrapping.

When a node issues a new block, it uses the highest (most difficult) PoW score configured for the milestones with index [𝑡, 𝑡 + 𝛽] where 𝑡 is the Latest Solid Milestone Index (LSMI) and 𝛽 is the _Max Activation Period_. This represents the most concervative approach, as it assures that no matter how high the network latency is, the PoW score is sufficient.

Apart from the general validity, the PoW of blocks is not considered when tips are selected. In the worst case, a block with an old score is received by the coordinator shortly before it issues a new milestone activating a higher PoW score. In this case, such "old" blocks can be included in the Tangle.

## AIMD-based adaptation of PoW score

In the following we describe the deterministic algorithm used by the milestone issuer to determine the PoW score.

The milestone issuer counts the number of (newly) included blocks 𝑛ₜ by the milestone with index 𝑡, the so-called epoch 𝑡. It then sets a new PoW score depending on such a value. The new PoW score 𝑠' (`Next PoW Score`) will start having validity at epoch 𝑡 + 𝛽 (`Target Milestone Index`).

An AIMD algorithm modifies the PoW score if the value of 𝑛ₜ is lower than `T1` or larger than `T2`, where `T1` and `T2` are thresholds defined by the protocol. The pseudocode of the simple algorithm above, is depicted below:

At epoch 𝑡, the coordinator sets the PoW score 𝑠' valid starting from epoch 𝑡 + 𝛽.

```
if 𝑛ₜ < T1 AND s > pow_min then
𝑠' ← 𝑠 - pow_step
else if 𝑛ₜ > T2 then
𝑠' ← 𝑠 + 𝛾 · pow_step
```

In order to avoid sharp changes in the PoW score, it is possible to set the variable `pow_step` to the smallest possible unit. Additionally, `pow_min` defines the minimum possible PoW score.

# Rationale and alternatives

## AIMD with Moving Average

This proposal is the same as the one described in [AIMD-based adaptation of PoW score](#AIMD-based-adaptation-of-PoW-score) except in the way 𝑛ₜ is computed. In fact, instead of considering a single epoch, the coordinator may consider data for the last minute (12 epochs) and compute some averages. This would probably make the algorithm more robust against short bursts of traffic. If necessary, we can consider an exponential moving average or extend the sliding window to a larger time frame.

## Prediction

The coordinator can make a prediction on the expected number of blocks issued in the future epoch(s) based on past data. The input data will be the tuples (𝑛ᵢ, 𝑠ᵢ). ARIMA models, online learning or more sophisticated machine learning techniques can be used. The goal of the algorithm is to find the PoW score 𝑠' such that the number of blocks in the next epoch is maximized without the network being overloaded. Unlike the AIMD-based approaches described above, this approach permits sharper changes in the PoW score as the new value is not necessarily directly correlated with the previous PoW score.

## PoW Validity

When the PoW difficulty is only changed as soon as the corresponding milestone is received, this leads to inconsistencies when the same block is valid for some nodes and invalid for others. Even though this will eventually be resolved by whether the next milestone confirms this block or not, this still seems like an undesirable state. It would be much more consistent if the PoW of the block must respect the PoW score of the latest milestone in its pastcone, i.e. of the Youngest block Root Snapshot Index (YMRSI). When this definition is used, Next PoW Score Milestone Index is no longer needed, as a grace period does not need to be considered.
However, it needs to be evaluated what the computational complexity and overhead of figuring out the YMRSI of every new block is.

# Further optimization

Apart from the number of blocks issued in the past, it is possible to use more information to get a more accurate estimate of the network traffic. In particular, it is possible to build an algorithm that takes into account:
- Number of orphaned blocks in epoch 𝑡: a large number of orphaned blocks can refer to the presence of attackers; hence, although 𝑛ₜ can be large, the PoW score should not increase as this may favor the attacker.
- Time spent by computing the PoW: evaluating the distribution of the times spent by computing the PoW by users can adjust the PoW score even if the thresholds for changing score are not reached; for instance, if no specialized hardware is generating any traffic (visible by large PoW computation times), it may be reasonable to decrease the PoW score.

# Copyright

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