From 9877ec923527d71fefe7fa7ff9de8a2c81454da1 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Fri, 5 May 2023 10:29:45 +0200 Subject: [PATCH 001/157] Add TIP-39 skeleton --- tips/TIP-0039/tip-0039.md | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tips/TIP-0039/tip-0039.md diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md new file mode 100644 index 000000000..6744d818e --- /dev/null +++ b/tips/TIP-0039/tip-0039.md @@ -0,0 +1,42 @@ +--- +tip: TODO +title: TODO +description: TODO +author: TODO +discussions-to: TODO +status: Draft +type: Standards +layer: Core +created: 2023-05-03 +requires: TIP-19, TIP-20, TIP-21 and TIP-22 +--- + +# Table of Contents + +1. [Summary](#summary) +2. [Motivation](#motivation) +3. [Building Blocks](#building-blocks) +4. [Copyright](#copyright) + +# Summary + +# Motivation + +# Building Blocks + +## Data Types & Subschema Notation + +Data types and subschemas used throughout this TIP are defined in [TIP-21](../TIP-0021/tip-0021.md). + +## Global Protocol Parameters + +Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA)](../TIP-0022/tip-0022.md) and [TIP-32 (Shimmer)](../TIP-0032/tip-0032.md). + +## Transaction Payload + +[TIP-20](../TIP-0020/tip-0020.md) is the basis for output validation in this TIP. + +# Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + From f4578f44e83d5ee18d387632e88263ee9773bc7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 11 May 2023 12:54:22 +0200 Subject: [PATCH 002/157] Potential mana and design overview --- tips/TIP-0039/tip-0039.md | 68 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 6744d818e..86a53b8c6 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -19,11 +19,79 @@ requires: TIP-19, TIP-20, TIP-21 and TIP-22 4. [Copyright](#copyright) # Summary +This document defines the mana related concepts and the mana dynamics in the IOTA protocol. +The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana** as well as the **Block Issuance Credits** that Mana can be alloted to. # Motivation +Mana is a measure of reputation and is used to determine the allowed throupught of an account and as a payment form of the block issuance. +We introduce the mana burn mechanism, in which a certain amount is burned from an account, each time user send a block. + +Mana is needed to write to the ledger, while staking is required for the protocol's security. + # Building Blocks +## Mana design +Mana is a core element of the IOTA incentivation scheme. It is a resource that can be obtained through: + * generating by holding IOTA tokens + * as a reward for staking IOTA tokens + * as a reward for delegating IOTA tokens + * or simply received from other IOTA users. + +It is an essential element of the IOTA protocol, as it is used to: + * determine the allowed throughput of an account + * as a payment form for the block issuance + +The following solutions are designed around the newest Iota Congestion Control Algorithm (ICCA) with Mana Credits. +Additionally, Mana implementation is strictly connected to the accounts introduced in [TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivation scheme. + +**Mana** can have different forms, each of which is described in the following sections. + +* Mana's main form is the [**Stored Mana**](#stored-mana). It is the UTXO-base form of the mana that can be moved within certain rules between the different owners, what allows for mana market development. +* The [**Potential Mana**](#potential-mana) is the second form of mana, which is generated by holding IOTA tokens. It represents the newly generated mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. +* When user spends the IOTA tokens, he is obliged to transition the potential mana to its more explicit form, mentioned before stored mana and storing the resource directly in the UTXO ledger, or user can convert mana to [**Block Issuance Credits (BIC)**](#block-issuance-credit-bic). + +We refer to the mana holdings as to the sum of all the potential mana and stored mana that the user owns. + +## Mana burn +According to the ICCA with Mana Credits mechanism, during each block issuance the user needs to burn a certain amount of Block Issuance Credits dictated by the RMC. +Therefore, to use the mana as a payment for the access to the network user needs to firstly allot the mana to its account's, thus convert it during the transaction to BIC. + +### RMC + +## Mana decay +Mana decay is introduced as a control mechanism of the mana dynamics, altogether with the rate for the mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. +To guarantee non-gameability (any certain behavior, e.g., splitting accounts, cannot be profitable for the user) and the fairness of mana, the decay factor needs to be applied to all forms of mana: + +- Newly generated Mana ([Potential mana section](#Potential-Mana)) +- Mana stored in UTXOs ([Stored Mana section](#Stored-Mana)) +- Mana bound to accounts for block issuance ([Block Issuance Credit section](#Block-Issuance-Credit-BIC)) +- Mana rewarded for staking and delegation ([Mana rewards section](#Mana-rewards)) + +As the form in which the decay factor will be applied might differ between the mana types, it is essential to point out that all of them are based on the same exponential decay, with the same parameter $\beta$. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. + +Applying decay for the generation of new mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on timestamps, not local times. For block issuance credit, which lives in an account, we advise applying the decay function in a slot-based manner and updating it at the end of each slot. + + +### Potential Mana +**Potential mana** is a raw form of mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not generates potential mana from the output `i` according to this formula, which already includes the decay: + +```math +\frac{\text{IOTA}_i}{\beta}*\Big(1 - e^{-\beta(t - t_i)}\Big), +``` +where $\text{IOTA}_i$ is the amount of IOTA tokens held in output `i`, $\beta$ is the global decay parameter for all kinds of Mana, $t$ is the timestamp of the transaction (consuming output `i`) being validated, and $t_i$ is the timestamp of when output `i` was created. + +The view on the potential mana value can be deterministically derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (creation time is the timestamp of the transaction). + +When the UTXO is spent the potential mana is lost, therefore user needs to specify what should happen to the accumulated potential mana value. There are three options: + - transition to Stored Mana: + the amount of potential mana transitioned to the stored mana form needs to be placed in the newly created output on the output side of the transaction + - transition to BIC: + the amount of potential mana that should be allotted to the account in form of a Block Issuance Credits should be specified in the `AccountAllottment` field of the transaction. + - ignored: + generated mana can be ignored, so that it will be destroyed during the transaction + + ## Data Types & Subschema Notation Data types and subschemas used throughout this TIP are defined in [TIP-21](../TIP-0021/tip-0021.md). From 52e83da8b40e1164bfeecef2d9a32b5df1f8233c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Mon, 15 May 2023 12:20:30 +0200 Subject: [PATCH 003/157] wip --- tips/TIP-0039/tip-0039.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 86a53b8c6..6c1476d48 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -8,7 +8,7 @@ status: Draft type: Standards layer: Core created: 2023-05-03 -requires: TIP-19, TIP-20, TIP-21 and TIP-22 +requires: TIP-42 --- # Table of Contents @@ -20,19 +20,16 @@ requires: TIP-19, TIP-20, TIP-21 and TIP-22 # Summary This document defines the mana related concepts and the mana dynamics in the IOTA protocol. -The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana** as well as the **Block Issuance Credits** that Mana can be alloted to. +The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana** as well as the **Block Issuance Credits (BIC)** that Mana can be allotted to. # Motivation -Mana is a measure of reputation and is used to determine the allowed throupught of an account and as a payment form of the block issuance. -We introduce the mana burn mechanism, in which a certain amount is burned from an account, each time user send a block. - -Mana is needed to write to the ledger, while staking is required for the protocol's security. - +Mana is a resource used to determine the allowed throughput of a user and as a payment form for the block issuance in the mana burn mechanism. +Mana can be obtained by actions helpful and profitable for the network, like token holding or engagement in securing the network. Additionally, it is necessary to use the network, so it plays the core role in th Iota tokenomics. Following document gives an high level overview of mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of BIC is burned from an account, each time user sends a block. Also in order to allot and use fully all the mana functionalities user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). # Building Blocks ## Mana design -Mana is a core element of the IOTA incentivation scheme. It is a resource that can be obtained through: +Mana is a core element of the IOTA inactivation scheme. It is a resource that can be obtained through: * generating by holding IOTA tokens * as a reward for staking IOTA tokens * as a reward for delegating IOTA tokens From 9d4e06188f42d738e1eb8374c7f1a8464fbbccc4 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Wed, 24 May 2023 17:59:49 +0200 Subject: [PATCH 004/157] Add stored Mana --- tips/TIP-0039/tip-0039.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 6c1476d48..8130518a9 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -88,6 +88,19 @@ When the UTXO is spent the potential mana is lost, therefore user needs to speci - ignored: generated mana can be ignored, so that it will be destroyed during the transaction +### Stored Mana + +**Stored Mana** is contained in outputs, just like IOTA tokens. Specifically, the `Mana Amount` field of an output represents the amount of stored Mana at the output's creation time, without decay being applied, until the time when the output is consumed. Therefore, the creation time of each output with stored Mana is required to calculate the decay of stored Mana. + +The stored Mana decay is applied whenever the output containing that stored Mana is consumed. The amount of stored Mana must be decayed before stored Mana is transferred into a new output according to the following formula: + +```math +\text{Mana Amount}_i(t) * e^{-\beta(t - t_i)}, +``` + +where $\text{Mana Amount}_i(t)$ is the amount of stored Mana held in output `i` at time $t$, $\beta$ is the global decay parameter, $t$ is the time of when the transaction consumes output `i`, and $t_i$ is the time of when output `i` was created. + +Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements.The following output types are able to hold stored Mana using the `Mana Amount` field: Basic Output, NFT Output, and Account Output. Note that Foundry Output is not able to hold stored Mana. Stored Mana is soulbound to an account. To transfer stored or potential Mana freely from one account to another, Mana sales outputs will be introduced. It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. ## Data Types & Subschema Notation @@ -104,4 +117,3 @@ Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA # Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). - From 2d6ca1842ee0fde26cd38f4bd39723b521584bd7 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Thu, 25 May 2023 10:41:14 +0200 Subject: [PATCH 005/157] Update preamble --- tips/TIP-0039/tip-0039.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 8130518a9..1cdf727e8 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -1,7 +1,7 @@ --- -tip: TODO -title: TODO -description: TODO +tip: 39 +title: Mana for IOTA 2.0 +description: Define Mana, Mana dynamics, and other Mana-related concepts in the IOTA 2.0 protocol author: TODO discussions-to: TODO status: Draft From 8385073512422ae430359f476c5e7cc24be72fb6 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Thu, 25 May 2023 11:21:35 +0200 Subject: [PATCH 006/157] Update ToC, fix typos, improve stored Mana --- tips/TIP-0039/tip-0039.md | 95 ++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 1cdf727e8..d244d7e07 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -16,91 +16,112 @@ requires: TIP-42 1. [Summary](#summary) 2. [Motivation](#motivation) 3. [Building Blocks](#building-blocks) + - [Mana design](#mana-design) + - [Mana burn](#mana-burn) + - [Mana decay](#mana-decay) + - [Potential Mana](#potential-mana) + - [Stored Mana](#stored-mana) + - [Block Issuance Credit](#block-issuance-credit) + - [Mana rewards](#mana-rewards) 4. [Copyright](#copyright) # Summary -This document defines the mana related concepts and the mana dynamics in the IOTA protocol. -The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana** as well as the **Block Issuance Credits (BIC)** that Mana can be allotted to. +This document defines the Mana related concepts and the Mana dynamics in the IOTA 2.0 protocol. +The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana,** as well as the **Block Issuance Credit (BIC)** that Mana can be allotted to. # Motivation -Mana is a resource used to determine the allowed throughput of a user and as a payment form for the block issuance in the mana burn mechanism. -Mana can be obtained by actions helpful and profitable for the network, like token holding or engagement in securing the network. Additionally, it is necessary to use the network, so it plays the core role in th Iota tokenomics. Following document gives an high level overview of mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of BIC is burned from an account, each time user sends a block. Also in order to allot and use fully all the mana functionalities user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). +Mana is a resource used to determine the allowed throughput of a user and as a payment form for the block issuance in the Mana burn mechanism. +Mana can be obtained by actions helpful and profitable for the network, like token holding or engagement in securing the network. Additionally, it is necessary to use the network, so it plays the core role in the IOTA tokenomics. Following document gives a high level overview of Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of BIC is burned from an account each time a user sends a block. Also, in order to allot and use fully all the Mana functionalities, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). # Building Blocks ## Mana design Mana is a core element of the IOTA inactivation scheme. It is a resource that can be obtained through: - * generating by holding IOTA tokens - * as a reward for staking IOTA tokens - * as a reward for delegating IOTA tokens + * generating by holding IOTA tokens; + * as a reward for staking IOTA tokens; + * as a reward for delegating IOTA tokens; * or simply received from other IOTA users. It is an essential element of the IOTA protocol, as it is used to: - * determine the allowed throughput of an account - * as a payment form for the block issuance + * determine the allowed throughput of an account; + * as a payment form for the block issuance. The following solutions are designed around the newest Iota Congestion Control Algorithm (ICCA) with Mana Credits. Additionally, Mana implementation is strictly connected to the accounts introduced in [TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivation scheme. -**Mana** can have different forms, each of which is described in the following sections. +**Mana** can have different forms, each of which is described in the following sections. -* Mana's main form is the [**Stored Mana**](#stored-mana). It is the UTXO-base form of the mana that can be moved within certain rules between the different owners, what allows for mana market development. -* The [**Potential Mana**](#potential-mana) is the second form of mana, which is generated by holding IOTA tokens. It represents the newly generated mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. -* When user spends the IOTA tokens, he is obliged to transition the potential mana to its more explicit form, mentioned before stored mana and storing the resource directly in the UTXO ledger, or user can convert mana to [**Block Issuance Credits (BIC)**](#block-issuance-credit-bic). +* [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved within certain rules between the different owners, which allows for mana market development. +* [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. +* When user spends the IOTA tokens, he is obliged to transition accumulated Potential mana to its more explicit form, mentioned before Stored mana and storing the resource directly in the UTXO ledger, or user can convert mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). -We refer to the mana holdings as to the sum of all the potential mana and stored mana that the user owns. +We refer to the **Mana holdings** as to the sum of all the potential Mana and stored Mana that the user owns. ## Mana burn -According to the ICCA with Mana Credits mechanism, during each block issuance the user needs to burn a certain amount of Block Issuance Credits dictated by the RMC. -Therefore, to use the mana as a payment for the access to the network user needs to firstly allot the mana to its account's, thus convert it during the transaction to BIC. +According to the ICCA with Mana Credits mechanism, during each block issuance, the user needs to burn a certain amount of Block Issuance Credit dictated by the RMC. +Therefore, to use Mana as a payment for the access to the network, the user needs to firstly allot Mana to their account, thus convert it during the transaction to BIC. ### RMC +TODO ## Mana decay -Mana decay is introduced as a control mechanism of the mana dynamics, altogether with the rate for the mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. -To guarantee non-gameability (any certain behavior, e.g., splitting accounts, cannot be profitable for the user) and the fairness of mana, the decay factor needs to be applied to all forms of mana: +Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. +To guarantee non-gameability (any certain behavior, e.g., splitting accounts, cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs to be applied to all forms of Mana: -- Newly generated Mana ([Potential mana section](#Potential-Mana)) -- Mana stored in UTXOs ([Stored Mana section](#Stored-Mana)) -- Mana bound to accounts for block issuance ([Block Issuance Credit section](#Block-Issuance-Credit-BIC)) -- Mana rewarded for staking and delegation ([Mana rewards section](#Mana-rewards)) +- newly generated Mana ([Potential Mana ](#potential-mana)); +- Mana stored in UTXOs ([Stored Mana](#stored-mana)); +- Mana bound to accounts for block issuance ([Block Issuance Credit](#block-issuance-credit)); +- Mana rewarded for staking and delegation ([Mana rewards](#mana-rewards)). -As the form in which the decay factor will be applied might differ between the mana types, it is essential to point out that all of them are based on the same exponential decay, with the same parameter $\beta$. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. +As the form in which the decay factor will be applied might differ between the Mana types, it is essential to point out that all of them are based on the same exponential decay, with the same parameter $\beta$. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. -Applying decay for the generation of new mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on timestamps, not local times. For block issuance credit, which lives in an account, we advise applying the decay function in a slot-based manner and updating it at the end of each slot. +Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on timestamps, not local times. For block issuance credit, which lives in an account, we advise applying the decay function in a slot-based manner and updating it at the end of each slot. -### Potential Mana -**Potential mana** is a raw form of mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not generates potential mana from the output `i` according to this formula, which already includes the decay: +## Potential Mana +**Potential Mana** is a raw form of mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not, generates potential Mana from the output `i` according to this formula, which already includes the decay: ```math \frac{\text{IOTA}_i}{\beta}*\Big(1 - e^{-\beta(t - t_i)}\Big), ``` where $\text{IOTA}_i$ is the amount of IOTA tokens held in output `i`, $\beta$ is the global decay parameter for all kinds of Mana, $t$ is the timestamp of the transaction (consuming output `i`) being validated, and $t_i$ is the timestamp of when output `i` was created. -The view on the potential mana value can be deterministically derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (creation time is the timestamp of the transaction). +The view on the potential Mana value can be deterministically derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the timestamp of the transaction). -When the UTXO is spent the potential mana is lost, therefore user needs to specify what should happen to the accumulated potential mana value. There are three options: - - transition to Stored Mana: - the amount of potential mana transitioned to the stored mana form needs to be placed in the newly created output on the output side of the transaction +When the UTXO is spent the potential Mana is lost, therefore the user needs to specify what should happen to the accumulated potential Mana value. There are three options: + - transition to stored Mana: + the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - transition to BIC: - the amount of potential mana that should be allotted to the account in form of a Block Issuance Credits should be specified in the `AccountAllottment` field of the transaction. + the amount of potential Mana that should be allotted to the account in form of a Block Issuance Credit (BIC) should be specified in the `AccountAllottment` field of the transaction; - ignored: - generated mana can be ignored, so that it will be destroyed during the transaction + generated Mana can be ignored, so that it will be destroyed during the transaction. -### Stored Mana +## Stored Mana -**Stored Mana** is contained in outputs, just like IOTA tokens. Specifically, the `Mana Amount` field of an output represents the amount of stored Mana at the output's creation time, without decay being applied, until the time when the output is consumed. Therefore, the creation time of each output with stored Mana is required to calculate the decay of stored Mana. +**Stored Mana** is contained in outputs, just like IOTA tokens. +Specifically, the `Mana Amount` field of an output represents the amount of stored Mana at the output's creation time, without decay being applied, until the time when the output is consumed. +Therefore, the creation time of each output with stored Mana is required to calculate the decay of stored Mana. -The stored Mana decay is applied whenever the output containing that stored Mana is consumed. The amount of stored Mana must be decayed before stored Mana is transferred into a new output according to the following formula: +The stored Mana decay is applied whenever the output containing that stored Mana is consumed. +The amount of stored Mana must be decayed before stored Mana is transferred into a new output according to the following formula: ```math \text{Mana Amount}_i(t) * e^{-\beta(t - t_i)}, ``` -where $\text{Mana Amount}_i(t)$ is the amount of stored Mana held in output `i` at time $t$, $\beta$ is the global decay parameter, $t$ is the time of when the transaction consumes output `i`, and $t_i$ is the time of when output `i` was created. +where $\text{Mana Amount}_i(t)$ is the amount of stored Mana held in output `i` at time $t$, $\beta$ is the global decay parameter, $t$ is the time of when the transaction consumes output `i`, +and $t_i$ is the time of when output `i` was created. -Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements.The following output types are able to hold stored Mana using the `Mana Amount` field: Basic Output, NFT Output, and Account Output. Note that Foundry Output is not able to hold stored Mana. Stored Mana is soulbound to an account. To transfer stored or potential Mana freely from one account to another, Mana sales outputs will be introduced. It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. +Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. +The following output types are able to hold stored Mana using the `Mana Amount` field: Basic Output, NFT Output, and Account Output. Note that Foundry Output is not able to hold stored Mana. + +Stored Mana is soulbound to an account. Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be used for congestion control; +it must first be allotted to an account in the form of BIC. To transfer stored or potential Mana freely from one account to another, Mana sales outputs will be introduced. +It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. + +## Block Issuance Credit + +## Mana rewards ## Data Types & Subschema Notation From 278c42f44293a9b9f539616a9bbcd8acc68848f7 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Thu, 25 May 2023 12:02:07 +0200 Subject: [PATCH 007/157] Add BIC --- tips/TIP-0039/img/gFLB1Ms.png | Bin 0 -> 204462 bytes tips/TIP-0039/tip-0039.md | 66 +++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tips/TIP-0039/img/gFLB1Ms.png diff --git a/tips/TIP-0039/img/gFLB1Ms.png b/tips/TIP-0039/img/gFLB1Ms.png new file mode 100644 index 0000000000000000000000000000000000000000..8eefd208ecb567ead8e7c6714683f04ef0eed5b5 GIT binary patch literal 204462 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
CQN)ZD>k%8LE9-51aAnZezruPWFjk@N&&%=b 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%0D1B4m#%Op4MV@-(GqLxAHSpcnI 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 e|8rf&=H?wqi Date: Thu, 25 May 2023 17:55:44 +0200 Subject: [PATCH 008/157] Add Mana rewards --- tips/TIP-0039/tip-0039.md | 43 +++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index b5dc2ad76..842193454 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -51,9 +51,12 @@ Additionally, Mana implementation is strictly connected to the accounts introduc **Mana** can have different forms, each of which is described in the following sections. -* [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved within certain rules between the different owners, which allows for mana market development. -* [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. -* When user spends the IOTA tokens, he is obliged to transition accumulated Potential mana to its more explicit form, mentioned before Stored mana and storing the resource directly in the UTXO ledger, or user can convert mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). +* [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved within certain rules between the different owners, which allows for Mana market development. +* [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. +It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. +* When user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit form, +mentioned before stored Mana and storing the resource directly in the UTXO ledger, or user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). +* [Mana rewards](#mana-rewards) is another form of Mana used to reward for participation in staking for validation and delegating IOTA tokens. We refer to the **Mana holdings** as to the sum of all the potential Mana and stored Mana that the user owns. @@ -79,12 +82,16 @@ Applying decay for the generation of new Mana and staking rewards is straightfor ## Potential Mana -**Potential Mana** is a raw form of mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not, generates potential Mana from the output `i` according to this formula, which already includes the decay: +**Potential Mana** is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not, generates potential Mana from the output `i` according to this formula, which already includes the decay: ```math \frac{\text{IOTA}_i}{\beta}*\Big(1 - e^{-\beta(t - t_i)}\Big), ``` -where $\text{IOTA}_i$ is the amount of IOTA tokens held in output `i`, $\beta$ is the global decay parameter for all kinds of Mana, $t$ is the timestamp of the transaction (consuming output `i`) being validated, and $t_i$ is the timestamp of when output `i` was created. +where +* $\text{IOTA}_i$ is the amount of IOTA tokens held in output `i`; +* $\beta$ is the global decay parameter for all forms of Mana; +* $t$ is the slot index of the transaction (consuming output `i`) being validated; +* $t_i$ is the slot index of when output `i` was created. The view on the potential Mana value can be deterministically derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the timestamp of the transaction). @@ -109,8 +116,11 @@ The amount of stored Mana must be decayed before stored Mana is transferred into \text{Mana Amount}_i(t) * e^{-\beta(t - t_i)}, ``` -where $\text{Mana Amount}_i(t)$ is the amount of stored Mana held in output `i` at time $t$, $\beta$ is the global decay parameter, $t$ is the time of when the transaction consumes output `i`, -and $t_i$ is the time of when output `i` was created. +where +* *$\text{Mana Amount}_i(t)$ is the amount of stored Mana held in output `i` at slot index $t$; +* $\beta$ is the global decay parameter for all forms of Mana; +* $t$ is the slot index of the transaction consumes output `i`; +* $t_i$ is the slot index of when output `i` was created. Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. The following output types are able to hold stored Mana using the `Mana Amount` field: Basic Output, NFT Output, and Account Output. Note that Foundry Output is not able to hold stored Mana. @@ -167,7 +177,7 @@ Notice that this Mana has to be decayed by a factor proportional to the differen \text{BIC}_i =\text{BIC}_{i-1} * e^{-\beta\Delta}-\sum \text{Burnt BIC}+\sum \text{Decayed allotted BIC}, ``` -where $\text{BIC}_i$ is the amount of BIC held by account `i` at the end of the slot commitment, $\beta$ is the global decay parameter for all kinds of Mana, $\Delta$ is the duration of time slot. +where $\text{BIC}_i$ is the amount of BIC held by account `i` at the end of the slot commitment, $\beta$ is the global decay parameter for all forms of Mana, $\Delta$ is the duration of time slot. - **BIC updates**: - _Increase_: happens upon slot commitment. @@ -185,7 +195,22 @@ Therefore, a block must contain an account's permission (i.e., a digital signatu - The required burning amount for a block is calculated with the Reference Mana Cost (RMC), which depends on the past network activity and gets updated every slot. ## Mana rewards -TODO + +Mana rewards are used to reward for participation in staking for validation and delegating IOTA tokens. +Rewarding validators and delegators with Mana is reasonable as it does not extract value from other IOTA token holders. + +Mana rewards are calculated on a per-slot basis; however, they become available to be claimed at slot commitments. +Mana rewards must be claimed by creating a transaction that consumes the original output that was staked or delegated and includes the Mana reward as stored Mana on the output side of the transaction. +As all other forms of Mana, decay must be applied to Mana rewards as well according to the following formula: + +```math +R(n) * e^{-\beta\Delta}, +``` + +where +* $R(n)$ is the amount of Mana rewards available to be claimed for staking or delegation in slot `n`; +* $\beta$ is the global decay parameter for all forms of Mana; +* $\Delta$ is the difference in the slot index of when Mana rewards are claimed and the index of slot for which staking or delegation was done. ## Data Types & Subschema Notation From 05727b8974f90c92b1c4b0ee4e7d580cdba7d87f Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Thu, 25 May 2023 17:57:51 +0200 Subject: [PATCH 009/157] Minor corrections to Mana rewards --- tips/TIP-0039/tip-0039.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 842193454..aa7493f8c 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -56,7 +56,7 @@ Additionally, Mana implementation is strictly connected to the accounts introduc It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. * When user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit form, mentioned before stored Mana and storing the resource directly in the UTXO ledger, or user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). -* [Mana rewards](#mana-rewards) is another form of Mana used to reward for participation in staking for validation and delegating IOTA tokens. +* [**Mana rewards**](#mana-rewards) is another form of Mana used to reward for participation in staking for validation and delegating IOTA tokens. We refer to the **Mana holdings** as to the sum of all the potential Mana and stored Mana that the user owns. @@ -201,6 +201,7 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra Mana rewards are calculated on a per-slot basis; however, they become available to be claimed at slot commitments. Mana rewards must be claimed by creating a transaction that consumes the original output that was staked or delegated and includes the Mana reward as stored Mana on the output side of the transaction. + As all other forms of Mana, decay must be applied to Mana rewards as well according to the following formula: ```math From c34d1ab83d5bd0770f3b9ae81c693b08c39fdb6f Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Fri, 26 May 2023 12:35:23 +0200 Subject: [PATCH 010/157] Try changing stored Mana to TIPs style --- tips/TIP-0039/tip-0039.md | 68 +++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index aa7493f8c..f17ca6077 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -46,7 +46,7 @@ It is an essential element of the IOTA protocol, as it is used to: * determine the allowed throughput of an account; * as a payment form for the block issuance. -The following solutions are designed around the newest Iota Congestion Control Algorithm (ICCA) with Mana Credits. +The following solutions are designed around the newest IOTA Congestion Control Algorithm (ICCA) with Mana Credits. Additionally, Mana implementation is strictly connected to the accounts introduced in [TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivation scheme. **Mana** can have different forms, each of which is described in the following sections. @@ -105,29 +105,49 @@ When the UTXO is spent the potential Mana is lost, therefore the user needs to s ## Stored Mana -**Stored Mana** is contained in outputs, just like IOTA tokens. -Specifically, the `Mana Amount` field of an output represents the amount of stored Mana at the output's creation time, without decay being applied, until the time when the output is consumed. -Therefore, the creation time of each output with stored Mana is required to calculate the decay of stored Mana. - -The stored Mana decay is applied whenever the output containing that stored Mana is consumed. -The amount of stored Mana must be decayed before stored Mana is transferred into a new output according to the following formula: - -```math -\text{Mana Amount}_i(t) * e^{-\beta(t - t_i)}, -``` - -where -* *$\text{Mana Amount}_i(t)$ is the amount of stored Mana held in output `i` at slot index $t$; -* $\beta$ is the global decay parameter for all forms of Mana; -* $t$ is the slot index of the transaction consumes output `i`; -* $t_i$ is the slot index of when output `i` was created. - -Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. -The following output types are able to hold stored Mana using the `Mana Amount` field: Basic Output, NFT Output, and Account Output. Note that Foundry Output is not able to hold stored Mana. - -Stored Mana is soulbound to an account. Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be used for congestion control; -it must first be allotted to an account in the form of BIC. To transfer stored or potential Mana freely from one account to another, Mana sales outputs will be introduced. -It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. +*Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA tokens) of Mana that can be transferred within certain rules between different users, +which allows for Mana market development. + +All output types except Foundry Outputs can hold stored Mana in the *Mana Amount* field. +This field represents the amount of stored Mana at the output's creation time until the time when the output is consumed without decay being applied to it. + +### Stored Mana Semantic Validation +- Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. +- Stored Mana must be soulbound to an account. +- Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be used for congestion control. It must first be allotted to an account in the form of BIC. +- *Mana Sales Outputs* must be used for transferring stored or potential Mana freely from one account to another. +- It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. +- Decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. +- To calculate decay of stored Mana, the creation time of each output with stored Mana must be contained in transactions. +- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: `Mana Amount * e^{-beta(Consumption Slot - Creation Slot)}`, where + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Mana Amountuint64 + The amount of stored Mana held by the output. +
Creation Slotuint64 + The slot index in which the output was created. +
Consumption Slotuint64 + The slot index in which the output is consumed. +
## Block Issuance Credit From 9fef0fc343b2870e8244de2056c127191dccb331 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Wed, 31 May 2023 12:21:50 +0200 Subject: [PATCH 011/157] Update Mana rewards to TIPs style --- tips/TIP-0039/tip-0039.md | 53 +++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index f17ca6077..087fb2bef 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -137,14 +137,14 @@ This field represents the amount of stored Mana at the output's creation time un Creation Slot uint64 - The slot index in which the output was created. + The index of slot in which the output was created. Consumption Slot uint64 - The slot index in which the output is consumed. + The index of slot in which the output is consumed. @@ -216,22 +216,43 @@ Therefore, a block must contain an account's permission (i.e., a digital signatu ## Mana rewards -Mana rewards are used to reward for participation in staking for validation and delegating IOTA tokens. +*Mana rewards* are used to reward for participation in staking for validation and delegating IOTA tokens. Rewarding validators and delegators with Mana is reasonable as it does not extract value from other IOTA token holders. -Mana rewards are calculated on a per-slot basis; however, they become available to be claimed at slot commitments. -Mana rewards must be claimed by creating a transaction that consumes the original output that was staked or delegated and includes the Mana reward as stored Mana on the output side of the transaction. - -As all other forms of Mana, decay must be applied to Mana rewards as well according to the following formula: - -```math -R(n) * e^{-\beta\Delta}, -``` - -where -* $R(n)$ is the amount of Mana rewards available to be claimed for staking or delegation in slot `n`; -* $\beta$ is the global decay parameter for all forms of Mana; -* $\Delta$ is the difference in the slot index of when Mana rewards are claimed and the index of slot for which staking or delegation was done. +### Mana Rewards Semantic Validation +- Mana rewards must be calculated on a per-slot basis. +- Mana rewards must become available for claiming at slot commitments. +- Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. +- Mana rewards must be put on outputs as stored Mana on the output side of the transaction. +- Decay must be applied to Mana rewards before they are put on outputs according to the following formula:: `Reward * e^{-beta(Claimimg Slot - Commitment Slot)}`, where + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Rewarduint64 + The amount of Mana rewards available to be claimed for staking or delegation for a specific slot. +
Commitment Slotuint64 + The index of slot in which that specific slot, for which Mana rewards are claimed, was committed. +
Claiming Slotuint64 + The index of slot in which Mana rewards are claimed. +
## Data Types & Subschema Notation From 8ff7061b52f9613996e62b381defbdab7ee43cfd Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Wed, 31 May 2023 12:42:01 +0200 Subject: [PATCH 012/157] Update potential Mana to TIPs style --- tips/TIP-0039/tip-0039.md | 62 ++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 087fb2bef..722b7da87 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -82,26 +82,46 @@ Applying decay for the generation of new Mana and staking rewards is straightfor ## Potential Mana -**Potential Mana** is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not, generates potential Mana from the output `i` according to this formula, which already includes the decay: - -```math -\frac{\text{IOTA}_i}{\beta}*\Big(1 - e^{-\beta(t - t_i)}\Big), -``` -where -* $\text{IOTA}_i$ is the amount of IOTA tokens held in output `i`; -* $\beta$ is the global decay parameter for all forms of Mana; -* $t$ is the slot index of the transaction (consuming output `i`) being validated; -* $t_i$ is the slot index of when output `i` was created. - -The view on the potential Mana value can be deterministically derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the timestamp of the transaction). - -When the UTXO is spent the potential Mana is lost, therefore the user needs to specify what should happen to the accumulated potential Mana value. There are three options: - - transition to stored Mana: - the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - - transition to BIC: - the amount of potential Mana that should be allotted to the account in form of a Block Issuance Credit (BIC) should be specified in the `AccountAllottment` field of the transaction; - - ignored: - generated Mana can be ignored, so that it will be destroyed during the transaction. +*Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. +Every IOTA token, whether storage deposit or not, generates potential Mana. +The view on the potential Mana value can be deterministically derived from the UTXO ledger, +based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the timestamp of the transaction). + +### Potential Mana Semantic Validation +- Potential Mana must and can only be consumed when the corresponding output is consumed. +- When the UTXO is spent, the potential Mana is lost, therefore the user must specify what should happen to the accumulated potential Mana value. There are three options: + - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; + - transition to BIC: the amount of potential Mana that should be allotted to the account in form of a Block Issuance Credit (BIC) should be specified in the `AccountAllottment` field of the transaction; + - ignored: generated Mana can be ignored, so that it will be destroyed during the transaction. +- Potential Mana must be calculated explicitly including decay as follows: `3 * Amount * (1 - e^{-beta(Consumption Slot - Creation Slot)})`, where + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Amountuint64 + The amount of IOTA tokens held in the output. +
Creation Slotuint64 + The index of slot in which the output was created. +
Consumption Slotuint64 + The index of slot in which the output is consumed. +
## Stored Mana @@ -224,7 +244,7 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra - Mana rewards must become available for claiming at slot commitments. - Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. - Mana rewards must be put on outputs as stored Mana on the output side of the transaction. -- Decay must be applied to Mana rewards before they are put on outputs according to the following formula:: `Reward * e^{-beta(Claimimg Slot - Commitment Slot)}`, where +- Decay must be applied to Mana rewards before they are put on outputs according to the following formula:: `Reward * e^{-beta(Claiming Slot - Commitment Slot)}`, where From 864e6e272625da5e9167f119412c73de09b84aea Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Wed, 31 May 2023 17:40:46 +0200 Subject: [PATCH 013/157] Update BIC to TIPs style --- tips/TIP-0039/tip-0039.md | 105 ++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 54 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 722b7da87..6f0321c48 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -58,13 +58,13 @@ It represents the newly generated Mana amounts from the IOTA holdings and is imp mentioned before stored Mana and storing the resource directly in the UTXO ledger, or user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). * [**Mana rewards**](#mana-rewards) is another form of Mana used to reward for participation in staking for validation and delegating IOTA tokens. -We refer to the **Mana holdings** as to the sum of all the potential Mana and stored Mana that the user owns. +The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. ## Mana burn According to the ICCA with Mana Credits mechanism, during each block issuance, the user needs to burn a certain amount of Block Issuance Credit dictated by the RMC. Therefore, to use Mana as a payment for the access to the network, the user needs to firstly allot Mana to their account, thus convert it during the transaction to BIC. -### RMC +### Reference Mana Cost TODO ## Mana decay @@ -78,14 +78,14 @@ To guarantee non-gameability (any certain behavior, e.g., splitting accounts, ca As the form in which the decay factor will be applied might differ between the Mana types, it is essential to point out that all of them are based on the same exponential decay, with the same parameter $\beta$. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. -Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on timestamps, not local times. For block issuance credit, which lives in an account, we advise applying the decay function in a slot-based manner and updating it at the end of each slot. +Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on slot indices, not local times. For block issuance credit, which lives in an account, it is advised applying the decay function in a slot-based manner and updating it at the end of each slot. ## Potential Mana *Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not, generates potential Mana. The view on the potential Mana value can be deterministically derived from the UTXO ledger, -based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the timestamp of the transaction). +based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the slot index of the transaction). ### Potential Mana Semantic Validation - Potential Mana must and can only be consumed when the corresponding output is consumed. @@ -171,68 +171,65 @@ This field represents the amount of stored Mana at the output's creation time un ## Block Issuance Credit -The purpose of **Block Issuance Credit (BIC**) is for congestion control, i.e., to pay for blocks to be scheduled and gossiped around the network and seen by everyone. -Congestion control manages which blocks should be gossiped to neighbours based on the block issuance credits burned by the block. It is important to distinguish between **blocks** and **transactions**: +*Block Issuance Credit (BIC)* Mana is used for congestion control, i.e., to pay for blocks to be scheduled and gossiped around the network and seen by everyone. +Congestion control manages which blocks should be gossiped to neighbours based on Mana burned from the block issuance credits by the block. +It is important to distinguish between **blocks** and **transactions**: congestion control only deals with blocks, which are the containers that carry transactions around the network. It does not care about the transactions inside the blocks. -Requirements for the block issuance credits can be divided based on the following categories: +The example below shows a ledger with a conflicting branch (perhaps due to a double spend), so only one branch (either the set of red or the set of green transactions) +can ultimately modify the ledger (UTXOs consumed), not both. However, all these blocks must be gossiped, whether they contain red or green transactions. +Thus, they must pay for the BIC used to get through schedulers regardless of whether the transaction within modify the ledger. +This is why Mana cannot be burned from BIC by a transaction, it can only be burned by a block. +![](./img/gFLB1Ms.png) -- **Representation of block issuance credits:** - - Block issuance credits are stored on a **per-account basis**. - - Accounts are represented by _Account Outputs_ on the UTXO ledger. The cost of permanently storing any outputs (until destruction) in the ledger is covered by the _storage deposit_. +### Block Issuance Credit Semantic Validation +- Block issuance credits must stored on a per-account basis. +- Accounts must be represented by _Account Outputs_ on the UTXO ledger. The cost of permanently storing any outputs (until destruction) in the ledger is covered by the _storage deposit_. Because of that, the number of accounts is capped at a number proportional to the max supply of tokens, contrary to the number of plain addresses. Because BIC must be tracked in slot commitments, keeping the number of entries (even though the user can create multiple accounts) in that data structure as small as possible is desirable. Using account IDs for that purpose is thus a good fit. - - The example below shows a ledger with a conflicting branch (perhaps due to a double spend), so only one branch (either the set of red or the set of green transactions) -can ultimately modify the ledger (UTXOs consumed), not both. However, all these blocks must be gossiped, whether they contain red or green transactions. -Thus, they must pay for the BIC used to get through schedulers regardless of whether the transaction within modify the ledger. -This is why **BIC can not be burned by a transaction, it can only be burned by a block**. -![](./img/gFLB1Ms.png) - - It is **not possible** to store BIC without an account output, because Mana can only be allotted to an account. +- It is not possible to store BIC without an Account Output because Mana can only be allotted as BIC to an account. Consequently, the ledger state is not bloated by having to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that requires a storage deposit -in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the BIC. - - We need a **commitment and time division mechanism**: current slot commitments present in IOTA 2.0. - - The end time of a slot is used for the decay calculation at the end of each slot. - - Definition of slots based on time of the genesis slot and a slot duration. - - The commitment mechanism per slot is needed to ensure the unified perception of the account-based BIC in the longer run. - - The **global agreement** on the BIC balances among all the nodes. - - It can be achieved by including the BIC vector to the slot commitments. This guarantees that all nodes have the same perception of the BIC balances from a certain point in time. - - If a block is orphaned, the block will not be included in a commitment and hence the balance of BIC of the account that issued the block will be **unaffected** by that block. - - If we burn BIC optimistically we need to reimburse the burned BIC when it is sure that the block will not be confirmed. - - All **reimbursements** need to happen at most during the slot commitment. - - At this point, all BIC optimistically burned for blocks that eventually were not accepted by the network need to be reimbursed as, after the slot is committed to, +in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the block issuance credits. +- A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. + - The end time of a slot is used for the decay calculation at the end of each slot. + - Definition of slots based on time of the genesis slot and a slot duration. + - The commitment mechanism per slot is needed to ensure the unified perception of the account-based BIC in the longer run. +- The global agreement on the BIC balances among all the nodes is required. + - It can be achieved by including the BIC vector to the slot commitments. This guarantees that all nodes have the same perception of the BIC balances from a certain point in time. +- If a block is orphaned, the block will not be included in a commitment, and hence, the balance of BIC of the account that issued the block must be unaffected by that block. + - If Mana is burned from BIC optimistically, the burned Mana from BIC must be reimbursed when it is sure that the block will not be confirmed. +- All reimbursements must happen at most during the slot commitment. + - At this point, all Mana optimistically burned from BIC for blocks that eventually were not accepted by the network must be reimbursed as, after the slot is committed to, no further changes in confirmation are possible. - - The time of the slot commitment should be used to align the local version of the BIC vector with the objective, committed version. - - It allow for the global control of the BIC dynamic with a **decay function**. - - Decreasing the BIC value over time is needed to encourage spending and discourage hoarding of BIC. - - This decrease needs also be applied to the potential and stored Mana so that users cannot gain by, e.g., delaying allotting. - - The balance of the BIC vector at the slot commitment should be the sum of: - - The balances of the previous committed BIC vector. - - All Mana allotted in accepted transactions of the committed slot. -Notice that this Mana has to be decayed by a factor proportional to the difference between the transaction timestamp and the end of the time slot. - - Subtract all BIC burned by accepted blocks of the committed slots. - - **Decay** is applied at the end of the slot commitment: +- The time of the slot commitment must be used to align the local version of the BIC vector with the objective, committed version. +It allows for the global control of the BIC dynamic with a Mana decay function. + - Decreasing the BIC value over time is needed to encourage spending and discourage hoarding of BIC. + - This decrease needs also be applied to the potential and stored Mana (that can be allotted to the account as BIC) so that users cannot gain by, e.g., delaying allotting. +- The balance of the BIC vector at the slot commitment must be the sum of: + - The balances of the previous committed BIC vector. + - All Mana allotted as BIC in accepted transactions of the committed slot. +Note that this Mana has to be decayed by a factor proportional to the difference between the transaction slot index and the end of the time slot. + - Subtract all Mana burned from BIC by accepted blocks of the committed slots. +- BIC updates (increase, deduction/Mana burning, Mana decay) must happen upon slot commitments. +Note that the implementation can decide to only update the stored BIC value whenever BIC is changed due to allotting or issuance of new blocks +(and decay the BIC value only when one of those events happen). In this case, there is the need to store and commit to the last time the BIC value was decayed. +- Mana decay must be applied at the end of each slot commitment according to formula: ```math -\text{BIC}_i =\text{BIC}_{i-1} * e^{-\beta\Delta}-\sum \text{Burnt BIC}+\sum \text{Decayed allotted BIC}, +\text{BIC}_{i+1} =\text{BIC}_i * e^{-\beta\Delta}-\sum \text{Burnt BIC}+\sum \text{Decayed allotted BIC}, ``` -where $\text{BIC}_i$ is the amount of BIC held by account `i` at the end of the slot commitment, $\beta$ is the global decay parameter for all forms of Mana, $\Delta$ is the duration of time slot. - -- **BIC updates**: - - _Increase_: happens upon slot commitment. - - _Deduction/burning_: happens upon slot commitment. - - _Decay_: applied upon each slot commitment. Note that the implementation can decide to only update the stored BIC value whenever BIC is changed due to allotting or issuance of new blocks -(and decay the BIC value only when one of those events happen). In this case, there is the need to store and commit to the last time the BIC value was decayed. +where $\text{BIC}_i$ is the amount of BIC held by account at the end of the slot commitment `i`, $\beta$ is the global decay parameter for all forms of Mana, $\Delta$ is the duration of time slot. -- **BIC burn and issuance of the blocks related**: - - A block needs to include the permission of an account from which BIC will be burned to pay for the block. - - The congestion control of nodes needs to burn BIC from an account when receiving a block. -Therefore, a block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that the account has authorized the block and that BIC can be burned from that account. - - The issuer needs to specify the amount burned. - - In the above-mentioned permission, the account owner needs to commit to a certain amount of BIC that will be burned. - - The declared burning amount must match the required burning for the current slot. - - The required burning amount for a block is calculated with the Reference Mana Cost (RMC), which depends on the past network activity and gets updated every slot. +- A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. + - The congestion control of nodes needs to burn Mana from BIC of an account when receiving a block. +Therefore, a block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that +the account has authorized the block and that Mana can be burned from BIC of that account. +- The issuer must specify the amount of Mana to be burned from BIC. + - In the above-mentioned permission, the account owner must commit to a certain amount of Mana that will be burned from BIC. +- The declared burning amount must match the required burning for the current slot. + - The required burning amount for a block is calculated with the Reference Mana Cost (RMC), which depends on the past network activity and gets updated every slot. ## Mana rewards @@ -244,7 +241,7 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra - Mana rewards must become available for claiming at slot commitments. - Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. - Mana rewards must be put on outputs as stored Mana on the output side of the transaction. -- Decay must be applied to Mana rewards before they are put on outputs according to the following formula:: `Reward * e^{-beta(Claiming Slot - Commitment Slot)}`, where +- Decay must be applied to Mana rewards before they are put on outputs according to the following formula: `Reward * e^{-beta(Claiming Slot - Commitment Slot)}`, where
Name
From 846e6259a63c072d64a135a1d53934dd4fa00ef8 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Wed, 31 May 2023 18:08:20 +0200 Subject: [PATCH 014/157] Add RMC --- tips/TIP-0039/tip-0039.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 6f0321c48..d4511ff79 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -61,15 +61,27 @@ mentioned before stored Mana and storing the resource directly in the UTXO ledge The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. ## Mana burn -According to the ICCA with Mana Credits mechanism, during each block issuance, the user needs to burn a certain amount of Block Issuance Credit dictated by the RMC. +According to the ICCA with Mana Credits mechanism, during each block issuance, the user needs to burn a certain amount of Block Issuance Credit (BIC) dictated by the Reference Mana Cost (RMC). Therefore, to use Mana as a payment for the access to the network, the user needs to firstly allot Mana to their account, thus convert it during the transaction to BIC. ### Reference Mana Cost -TODO +*Reference Mana Cost (RMC)* is used to decide upon commitment how much Mana is burned from BIC by each block in that slot. +RMC is computed according to an algorithm based on recent traffic activity: the algorithm counts the number of blocks in slots which are *Maximum Committable Age (MCA)* slots in the past, +so that all nodes agree on that value of RMC. + +From the high-level perspective, the RMC algorithm works as follows: +- If the number of blocks in slot `i-MCA` is larger than a given threshold, then the RMC increases. +- Otherwise, if the activity is low, the RMC decreases. +- The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes too large for the majority of users, and activity drops. + +The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid price manipulations by malicious actors. +Note that blocks from issuers with negative BIC balance are excluded with respect to the RMC calculation, but they do make part of the slot commitment. +To limit fluctuations in the RMC, it is proposed to update its value every MCA slots at least. ## Mana decay -Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. -To guarantee non-gameability (any certain behavior, e.g., splitting accounts, cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs to be applied to all forms of Mana: +Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, +which will be discussed in detail in the next sections. To guarantee non-gameability (any certain behavior, e.g., +splitting accounts, cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs to be applied to all forms of Mana: - newly generated Mana ([Potential Mana](#potential-mana)); - Mana stored in UTXOs ([Stored Mana](#stored-mana)); From 16a98566a17a2cd36973e72195e229f488a89080 Mon Sep 17 00:00:00 2001 From: Andrew Cullen <45826600+cyberphysic4l@users.noreply.github.com> Date: Fri, 2 Jun 2023 16:22:55 +0100 Subject: [PATCH 015/157] update Mana/BIC wording --- tips/TIP-0039/tip-0039.md | 65 ++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index d4511ff79..c6c27ca3b 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -13,17 +13,26 @@ requires: TIP-42 # Table of Contents -1. [Summary](#summary) -2. [Motivation](#motivation) -3. [Building Blocks](#building-blocks) - - [Mana design](#mana-design) - - [Mana burn](#mana-burn) - - [Mana decay](#mana-decay) - - [Potential Mana](#potential-mana) - - [Stored Mana](#stored-mana) - - [Block Issuance Credit](#block-issuance-credit) - - [Mana rewards](#mana-rewards) -4. [Copyright](#copyright) +- [Table of Contents](#table-of-contents) +- [Summary](#summary) +- [Motivation](#motivation) +- [Building Blocks](#building-blocks) + - [Mana design](#mana-design) + - [Mana burn](#mana-burn) + - [Reference Mana Cost](#reference-mana-cost) + - [Mana decay](#mana-decay) + - [Potential Mana](#potential-mana) + - [Potential Mana Semantic Validation](#potential-mana-semantic-validation) + - [Stored Mana](#stored-mana) + - [Stored Mana Semantic Validation](#stored-mana-semantic-validation) + - [Block Issuance Credit](#block-issuance-credit) + - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) + - [Mana rewards](#mana-rewards) + - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) + - [Data Types \& Subschema Notation](#data-types--subschema-notation) + - [Global Protocol Parameters](#global-protocol-parameters) + - [Transaction Payload](#transaction-payload) +- [Copyright](#copyright) # Summary This document defines the Mana related concepts and the Mana dynamics in the IOTA 2.0 protocol. @@ -31,7 +40,7 @@ The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Ma # Motivation Mana is a resource used to determine the allowed throughput of a user and as a payment form for the block issuance in the Mana burn mechanism. -Mana can be obtained by actions helpful and profitable for the network, like token holding or engagement in securing the network. Additionally, it is necessary to use the network, so it plays the core role in the IOTA tokenomics. Following document gives a high level overview of Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of BIC is burned from an account each time a user sends a block. Also, in order to allot and use fully all the Mana functionalities, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). +Mana can be obtained by actions helpful and profitable for the network, like token holding or engagement in securing the network. Additionally, it is necessary to use the network, so it plays the core role in the IOTA tokenomics. Following document gives a high level overview of Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of Mana is burned in each block which is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to their account to increase their BIC and ensure it does not go negative. In order to issue blocks, allot Mana and use fully all the Mana functionalities, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). # Building Blocks @@ -61,8 +70,7 @@ mentioned before stored Mana and storing the resource directly in the UTXO ledge The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. ## Mana burn -According to the ICCA with Mana Credits mechanism, during each block issuance, the user needs to burn a certain amount of Block Issuance Credit (BIC) dictated by the Reference Mana Cost (RMC). -Therefore, to use Mana as a payment for the access to the network, the user needs to firstly allot Mana to their account, thus convert it during the transaction to BIC. +According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a certain amount of Mana dictated by the size of the block and the Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Therefore, in order to prevent being locked out of their account, the block issuer must ensure that sufficient Mana is also allotted to their account to ensure their BIC balance remains non-negative. ### Reference Mana Cost *Reference Mana Cost (RMC)* is used to decide upon commitment how much Mana is burned from BIC by each block in that slot. @@ -90,7 +98,7 @@ splitting accounts, cannot be profitable for the user) and the fairness of Mana, As the form in which the decay factor will be applied might differ between the Mana types, it is essential to point out that all of them are based on the same exponential decay, with the same parameter $\beta$. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. -Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on slot indices, not local times. For block issuance credit, which lives in an account, it is advised applying the decay function in a slot-based manner and updating it at the end of each slot. +Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on slot indices, not local times. For block issuance credit, it is advised applying the decay function in a slot-based manner and updating it upon slot commitment. ## Potential Mana @@ -103,7 +111,7 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX - Potential Mana must and can only be consumed when the corresponding output is consumed. - When the UTXO is spent, the potential Mana is lost, therefore the user must specify what should happen to the accumulated potential Mana value. There are three options: - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - - transition to BIC: the amount of potential Mana that should be allotted to the account in form of a Block Issuance Credit (BIC) should be specified in the `AccountAllottment` field of the transaction; + - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; - ignored: generated Mana can be ignored, so that it will be destroyed during the transaction. - Potential Mana must be calculated explicitly including decay as follows: `3 * Amount * (1 - e^{-beta(Consumption Slot - Creation Slot)})`, where
Name
@@ -146,7 +154,7 @@ This field represents the amount of stored Mana at the output's creation time un ### Stored Mana Semantic Validation - Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. - Stored Mana must be soulbound to an account. -- Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be used for congestion control. It must first be allotted to an account in the form of BIC. +- Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be spent within a block. It must be allotted to an account's BIC in order to pay for Mana burned by blocks. - *Mana Sales Outputs* must be used for transferring stored or potential Mana freely from one account to another. - It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. - Decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. @@ -190,7 +198,7 @@ congestion control only deals with blocks, which are the containers that carry t The example below shows a ledger with a conflicting branch (perhaps due to a double spend), so only one branch (either the set of red or the set of green transactions) can ultimately modify the ledger (UTXOs consumed), not both. However, all these blocks must be gossiped, whether they contain red or green transactions. -Thus, they must pay for the BIC used to get through schedulers regardless of whether the transaction within modify the ledger. +Thus, they must pay for the BIC used to get through schedulers regardless of whether the transaction within modifies the ledger. This is why Mana cannot be burned from BIC by a transaction, it can only be burned by a block. ![](./img/gFLB1Ms.png) @@ -200,20 +208,16 @@ This is why Mana cannot be burned from BIC by a transaction, it can only be burn Because of that, the number of accounts is capped at a number proportional to the max supply of tokens, contrary to the number of plain addresses. Because BIC must be tracked in slot commitments, keeping the number of entries (even though the user can create multiple accounts) in that data structure as small as possible is desirable. Using account IDs for that purpose is thus a good fit. -- It is not possible to store BIC without an Account Output because Mana can only be allotted as BIC to an account. +- It is not possible to store BIC without an Account Output because Mana burned by blocks must also be deducted from BIC and the block cannot modify the Account Output. Consequently, the ledger state is not bloated by having to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that requires a storage deposit in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the block issuance credits. - A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. - The end time of a slot is used for the decay calculation at the end of each slot. - Definition of slots based on time of the genesis slot and a slot duration. - - The commitment mechanism per slot is needed to ensure the unified perception of the account-based BIC in the longer run. + - The commitment mechanism per slot is needed to ensure the unified perception of the BIC in the longer run. - The global agreement on the BIC balances among all the nodes is required. - It can be achieved by including the BIC vector to the slot commitments. This guarantees that all nodes have the same perception of the BIC balances from a certain point in time. - If a block is orphaned, the block will not be included in a commitment, and hence, the balance of BIC of the account that issued the block must be unaffected by that block. - - If Mana is burned from BIC optimistically, the burned Mana from BIC must be reimbursed when it is sure that the block will not be confirmed. -- All reimbursements must happen at most during the slot commitment. - - At this point, all Mana optimistically burned from BIC for blocks that eventually were not accepted by the network must be reimbursed as, after the slot is committed to, -no further changes in confirmation are possible. - The time of the slot commitment must be used to align the local version of the BIC vector with the objective, committed version. It allows for the global control of the BIC dynamic with a Mana decay function. - Decreasing the BIC value over time is needed to encourage spending and discourage hoarding of BIC. @@ -222,7 +226,7 @@ It allows for the global control of the BIC dynamic with a Mana decay function. - The balances of the previous committed BIC vector. - All Mana allotted as BIC in accepted transactions of the committed slot. Note that this Mana has to be decayed by a factor proportional to the difference between the transaction slot index and the end of the time slot. - - Subtract all Mana burned from BIC by accepted blocks of the committed slots. + - Subtract from BIC all Mana burned by accepted blocks of the committed slots. - BIC updates (increase, deduction/Mana burning, Mana decay) must happen upon slot commitments. Note that the implementation can decide to only update the stored BIC value whenever BIC is changed due to allotting or issuance of new blocks (and decay the BIC value only when one of those events happen). In this case, there is the need to store and commit to the last time the BIC value was decayed. @@ -232,15 +236,14 @@ Note that the implementation can decide to only update the stored BIC value when \text{BIC}_{i+1} =\text{BIC}_i * e^{-\beta\Delta}-\sum \text{Burnt BIC}+\sum \text{Decayed allotted BIC}, ``` -where $\text{BIC}_i$ is the amount of BIC held by account at the end of the slot commitment `i`, $\beta$ is the global decay parameter for all forms of Mana, $\Delta$ is the duration of time slot. +where $\text{BIC}_i$ is the BIC of the account at the end of the slot commitment `i`, $\beta$ is the global decay parameter for all forms of Mana, $\Delta$ is the duration of time slot. - A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. - - The congestion control of nodes needs to burn Mana from BIC of an account when receiving a block. -Therefore, a block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that + - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that the account has authorized the block and that Mana can be burned from BIC of that account. -- The issuer must specify the amount of Mana to be burned from BIC. - - In the above-mentioned permission, the account owner must commit to a certain amount of Mana that will be burned from BIC. -- The declared burning amount must match the required burning for the current slot. +- The issuer must specify the maximum amount of Mana they will allow to be burned from BIC. + - In the above-mentioned permission, the account owner must commit to a certain maximum amount of Mana that will be burned from BIC. +- The declared burning amount must be at least the required burning for the current slot. - The required burning amount for a block is calculated with the Reference Mana Cost (RMC), which depends on the past network activity and gets updated every slot. ## Mana rewards From b89cf1dbcad0fbacd92e90825cd8a0d8a08161fc Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sat, 3 Jun 2023 16:15:10 +0100 Subject: [PATCH 016/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 188 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 179 insertions(+), 9 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c6c27ca3b..3b446db65 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -113,7 +113,8 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; - ignored: generated Mana can be ignored, so that it will be destroyed during the transaction. -- Potential Mana must be calculated explicitly including decay as follows: `3 * Amount * (1 - e^{-beta(Consumption Slot - Creation Slot)})`, where +- Potential Mana must be calculated explicitly including decay as follows: + `Amount*f(Consumption Slot - Creation Slot)`, where
@@ -141,6 +142,89 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX The index of slot in which the output is consumed. + +And `f(n)` is an approximation of `Mana Generation * (1 - e^{-beta*SlotDuration*n})`, given by a lookup table. The reason for the use of a lookup table for this calculation is that floating point operations might lead to inconsistencies among results in different nodes. The table used is given below: + +
Name
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Lookup Table 1: Potential Mana generation
nf(n)nf(n)
002048
14096
28192
48640 (1 epoch)
817280 (2 epochs)
1634560 (4 epochs)
3269120 (8 epochs)
64138240 (16 epochs)
128276480 32 epochs)
256552960 (64 epochs)
5121105920 (128 epochs)
10242211840 (256 epochs)
## Stored Mana @@ -159,8 +243,9 @@ This field represents the amount of stored Mana at the output's creation time un - It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. - Decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. - To calculate decay of stored Mana, the creation time of each output with stored Mana must be contained in transactions. -- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: `Mana Amount * e^{-beta(Consumption Slot - Creation Slot)}`, where - +- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: `Mana Amount * g(Consumption Slot - Creation Slot)`, where + +
@@ -189,6 +274,90 @@ This field represents the amount of stored Mana at the output's creation time un
Name Type
+And `g(n)` is an approximation of `e^{-beta*SlotDuration*n}`, given by a lookup table. The reason for the use of a lookup table for this calculation is the same as for the Potential Mana calculations. The table used is given below: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Lookup Table 2: decays for Mana
nf(n)nf(n)
002048
14096
28192
48640 (1 epoch)
817280 (2 epochs)
1634560 (4 epochs)
3269120 (8 epochs)
64138240 (16 epochs)
128276480 (32 epochs)
256552960 (64 epochs)
5121105920 (128 epochs)
10242211840 (256 epochs)
+ + ## Block Issuance Credit *Block Issuance Credit (BIC)* Mana is used for congestion control, i.e., to pay for blocks to be scheduled and gossiped around the network and seen by everyone. @@ -212,7 +381,7 @@ Using account IDs for that purpose is thus a good fit. Consequently, the ledger state is not bloated by having to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that requires a storage deposit in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the block issuance credits. - A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. - - The end time of a slot is used for the decay calculation at the end of each slot. + - The end time of an epoch is used for the decay calculation at the end of each epoch. - Definition of slots based on time of the genesis slot and a slot duration. - The commitment mechanism per slot is needed to ensure the unified perception of the BIC in the longer run. - The global agreement on the BIC balances among all the nodes is required. @@ -225,18 +394,18 @@ It allows for the global control of the BIC dynamic with a Mana decay function. - The balance of the BIC vector at the slot commitment must be the sum of: - The balances of the previous committed BIC vector. - All Mana allotted as BIC in accepted transactions of the committed slot. -Note that this Mana has to be decayed by a factor proportional to the difference between the transaction slot index and the end of the time slot. +Note that, in the case of only decaying the BIC vector at the end of each epoch, this Mana has to be decayed by a factor proportional to the difference between the transaction slot index and the end of the epoch. - Subtract from BIC all Mana burned by accepted blocks of the committed slots. - BIC updates (increase, deduction/Mana burning, Mana decay) must happen upon slot commitments. Note that the implementation can decide to only update the stored BIC value whenever BIC is changed due to allotting or issuance of new blocks (and decay the BIC value only when one of those events happen). In this case, there is the need to store and commit to the last time the BIC value was decayed. -- Mana decay must be applied at the end of each slot commitment according to formula: +- Mana decay must be applied at the end of each epoch according to formula: ```math -\text{BIC}_{i+1} =\text{BIC}_i * e^{-\beta\Delta}-\sum \text{Burnt BIC}+\sum \text{Decayed allotted BIC}, +\text{BIC}_{i+1} =\text{BIC}_i * g(number of slots per epoch)-\sum \text{Burnt BIC}+\sum \text{Decayed allotted BIC}, ``` -where $\text{BIC}_i$ is the BIC of the account at the end of the slot commitment `i`, $\beta$ is the global decay parameter for all forms of Mana, $\Delta$ is the duration of time slot. +where $\text{BIC}_i$ is the amount of BIC held by account at the end of the slot commitment `i`, and `g(number of slots per epoch)` is given by the lookup Table 2 (decays for Mana). - A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that @@ -256,7 +425,7 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra - Mana rewards must become available for claiming at slot commitments. - Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. - Mana rewards must be put on outputs as stored Mana on the output side of the transaction. -- Decay must be applied to Mana rewards before they are put on outputs according to the following formula: `Reward * e^{-beta(Claiming Slot - Commitment Slot)}`, where +- Decay must be applied to Mana rewards before they are put on outputs according to the following formula: `Reward * g(Claiming Slot - Commitment Slot)`, where @@ -285,6 +454,7 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra
Name
+and `g(n)` is given by the lookup Table 2 (decays for Mana). ## Data Types & Subschema Notation From 3e3145f03a73b14dccb878f2759753ff6a2adafd Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 4 Jun 2023 20:21:23 +0100 Subject: [PATCH 017/157] Update tip-0039.md Changed to a single lookup table --- tips/TIP-0039/tip-0039.md | 99 ++++----------------------------------- 1 file changed, 10 insertions(+), 89 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 3b446db65..78052debb 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -115,6 +115,7 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX - ignored: generated Mana can be ignored, so that it will be destroyed during the transaction. - Potential Mana must be calculated explicitly including decay as follows: `Amount*f(Consumption Slot - Creation Slot)`, where + @@ -143,14 +144,16 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX -And `f(n)` is an approximation of `Mana Generation * (1 - e^{-beta*SlotDuration*n})`, given by a lookup table. The reason for the use of a lookup table for this calculation is that floating point operations might lead to inconsistencies among results in different nodes. The table used is given below: +And `f(n)` is an approximation of `Mana Generation * (1 - e^{-beta*SlotDuration*n})`, calculated with the aid of a lookup table. The reason for the use of a lookup table for this calculation is that floating point operations might lead to inconsistencies among results in different nodes. The values stored in the lookup table are an approximation of `e^{-beta*SlotDuration*n}`. All the operations to calculate `f(n)` must be done using fixed point arithmetics. Example: if `Mana Generation = e^{-beta*SlotDuration*n}) = 0.1`, and `Amount = 1001`, the potential Mana must be calculated as `1001 * 1/10 * (1 - 1/10) = 1001 * 1/10 * 9/10 = (1001 * 1 * 9)/100 = 9009/100 = 90` + +The table used is given below: -
Name
+
Lookup Table 1: Potential Mana generation
- + - + @@ -274,89 +277,7 @@ This field represents the amount of stored Mana at the output's creation time un
Lookup Table: Decays for Mana
nf(n)e^{-beta*SlotDuration*n} nf(n)e^{-beta*SlotDuration*n}
0
-And `g(n)` is an approximation of `e^{-beta*SlotDuration*n}`, given by a lookup table. The reason for the use of a lookup table for this calculation is the same as for the Potential Mana calculations. The table used is given below: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lookup Table 2: decays for Mana
nf(n)nf(n)
002048
14096
28192
48640 (1 epoch)
817280 (2 epochs)
1634560 (4 epochs)
3269120 (8 epochs)
64138240 (16 epochs)
128276480 (32 epochs)
256552960 (64 epochs)
5121105920 (128 epochs)
10242211840 (256 epochs)
- +And `g(n)` is an approximation of `e^{-beta*SlotDuration*n}`, given by a lookup table. The reason for the use of a lookup table for this calculation is the same as for the Potential Mana calculations. The table used is also the same as for the Potential Mana calculations, given by Lookup Table: Decays for Mana. ## Block Issuance Credit @@ -405,7 +326,7 @@ Note that the implementation can decide to only update the stored BIC value when \text{BIC}_{i+1} =\text{BIC}_i * g(number of slots per epoch)-\sum \text{Burnt BIC}+\sum \text{Decayed allotted BIC}, ``` -where $\text{BIC}_i$ is the amount of BIC held by account at the end of the slot commitment `i`, and `g(number of slots per epoch)` is given by the lookup Table 2 (decays for Mana). +where $\text{BIC}_i$ is the amount of BIC held by account at the end of the slot commitment `i`, and `g(number of slots per epoch)` is given by Lookup Table: Decays for Mana. - A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that @@ -454,7 +375,7 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra -and `g(n)` is given by the lookup Table 2 (decays for Mana). +and `g(n)` is given by Lookup Table: Decays for Mana. ## Data Types & Subschema Notation From cc2c34636cb03c71741d5170f04da2567b577c61 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 7 Jun 2023 11:27:43 +0100 Subject: [PATCH 018/157] lookup table in 2 columns --- tips/TIP-0039/tip-0039.md | 72 +++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 78052debb..96515df62 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -151,83 +151,103 @@ The table used is given below: - - - + - + + - + - + + + - + - + + + - + - + + + - + - + + + - + - + + + + + + + - + - + + + - + - + + + - + - + + + - + - + + + - + + + - - -
Lookup Table: Decays for Mana
ne^{-beta*SlotDuration*n}ne^{-beta*SlotDuration*n}e^{-beta*SlotDuration*n}
0 02048
1
12 4096
4
28 8192
16
432 8640 (1 epoch)
64
8128 17280 (2 epochs)
256
16512 34560 (4 epochs)
1024
2048
324096 69120 (8 epochs)
8192
648640 (1 epoch) 138240 (16 epochs)
17280 (2 epochs)
12834560 (4 epochs) 276480 32 epochs)
69120 (8 epochs)
256138240 (16 epochs) 552960 (64 epochs)
276480 32 epochs)
512552960 (64 epochs)
1105920 (128 epochs)
1024 2211840 (256 epochs)
## Stored Mana From dd5405e8f6e6ad9407805cc448f75a8bb5f36364 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 12 Jun 2023 09:04:54 +0100 Subject: [PATCH 019/157] General reestructure --- tips/TIP-0039/tip-0039.md | 296 +++++++++++++++++++++++--------------- 1 file changed, 178 insertions(+), 118 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 96515df62..eb5990d23 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -21,6 +21,8 @@ requires: TIP-42 - [Mana burn](#mana-burn) - [Reference Mana Cost](#reference-mana-cost) - [Mana decay](#mana-decay) + - [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) + - [How to use the lookup table](#how-to-use-the-lookup-table) - [Potential Mana](#potential-mana) - [Potential Mana Semantic Validation](#potential-mana-semantic-validation) - [Stored Mana](#stored-mana) @@ -87,8 +89,7 @@ Note that blocks from issuers with negative BIC balance are excluded with respec To limit fluctuations in the RMC, it is proposed to update its value every MCA slots at least. ## Mana decay -Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, -which will be discussed in detail in the next sections. To guarantee non-gameability (any certain behavior, e.g., +Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. To guarantee non-gameability (any certain behavior, e.g., splitting accounts, cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs to be applied to all forms of Mana: - newly generated Mana ([Potential Mana](#potential-mana)); @@ -100,156 +101,221 @@ As the form in which the decay factor will be applied might differ between the M Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on slot indices, not local times. For block issuance credit, it is advised applying the decay function in a slot-based manner and updating it upon slot commitment. +## Mana and fixed point arithmetics -## Potential Mana -*Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. -Every IOTA token, whether storage deposit or not, generates potential Mana. -The view on the potential Mana value can be deterministically derived from the UTXO ledger, -based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the slot index of the transaction). +Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding behaviour in different architectures. The results of the operations involving floating point variables might difer by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, diferences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviours in the system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. -### Potential Mana Semantic Validation -- Potential Mana must and can only be consumed when the corresponding output is consumed. -- When the UTXO is spent, the potential Mana is lost, therefore the user must specify what should happen to the accumulated potential Mana value. There are three options: - - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; - - ignored: generated Mana can be ignored, so that it will be destroyed during the transaction. -- Potential Mana must be calculated explicitly including decay as follows: - `Amount*f(Consumption Slot - Creation Slot)`, where +We introduce in this section a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of $2^{32}\exp(-\beta \text{ SlotDuration } n)$ for different values of $n$: - - - - - - - - - - - - - - - - - - - - - - -And `f(n)` is an approximation of `Mana Generation * (1 - e^{-beta*SlotDuration*n})`, calculated with the aid of a lookup table. The reason for the use of a lookup table for this calculation is that floating point operations might lead to inconsistencies among results in different nodes. The values stored in the lookup table are an approximation of `e^{-beta*SlotDuration*n}`. All the operations to calculate `f(n)` must be done using fixed point arithmetics. Example: if `Mana Generation = e^{-beta*SlotDuration*n}) = 0.1`, and `Amount = 1001`, the potential Mana must be calculated as `1001 * 1/10 * (1 - 1/10) = 1001 * 1/10 * 9/10 = (1001 * 1 * 9)/100 = 9009/100 = 90` - -The table used is given below: -
NameTypeDescription
Amountuint64 - The amount of IOTA tokens held in the output. -
Creation Slotuint64 - The index of slot in which the output was created. -
Consumption Slotuint64 - The index of slot in which the output is consumed. -
+
Lookup Table: Decays for Mana
- + + - - - - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + +
Lookup Table: Decays for Mana in slot granularity
ne^{-beta*SlotDuration*n}Typedecay(n)
00
11 (2^0)uint324294966388
22 (2^1)uint324294965480
44 (2^2)uint324294963664
88 (2^3)uint324294960032
1616 (2^4)uint324294952769
3232 (2^5)uint324294938242
6464 (2^6)uint324294909188
128128 (2^7)uint324294851080
256256 (2^8)uint324294734867
512512 (2^9)uint324294502451
10241024 (2^10)uint324294037656
20482048 (2^11)uint324293108217
40964096 (2^12)uint324291249942
81928192 (2^13)uint324287535805
8640 (1 epoch)16384 (2^14)uint324280117173
17280 (2 epochs)32768 (2^15)uint324265318395
34560 (4 epochs)65536 (2^16)uint324235874166
69120 (8 epochs)131072 (2^17)uint324177594080
138240 (16 epochs)262144 (2^18)uint324063428449
276480 32 epochs)524288 (2^19)uint323844371709
552960 (64 epochs)1048576 (2^20)uint323441049213
1105920 (128 epochs)2097152 (2^21)uint322756905669
2211840 (256 epochs)4194304 (2^22)uint321769636029
+### How to use the lookup table + +The table defined above only gives the values of `decay(n)` for some selected values of $n$ in the form of powers of 2. To calculate `decay(n)` for other $n$'s, we combine values of given $n$ using the following algorithm: + +- If $0> 32 + ``` + +- If $n\geq 2^{23}$: Let $\sum_{k=0}^{K}c_k 2^k=n$, i.e., let $(c_{K}, c_{K-1},...,c_1,c_0)$ be the binary representation of $n$. Let $m$ be the decimal representation of $(c_{K}, c_{K-1},...,c_{23},c_{22})$. + + ``` + value = uint64(2^32) + for i = 1,...,m: + value = [value*decay(2^22)] >> 32 + for k = 21,...,0: + if (ck == 1): + value = [value*decay(2^k)] >> 32 + ``` + + Notice that since the values in the table are type uint32, the multiplications in the algorithm have to be done using a uint64 variable to avoid overflowing. The final result can be stored as a uint32 value (if needed), since after the shift operation the result will be smaller than $2^{32}$. + +- If $n=0$, $\exp(-\beta \text{ SlotDuration } n)=1$. Thus, in this case, the decay (and the lookup table) should not be applied. + +Other implementations of the fuction are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial, since sequences of divisions and multiplications with integers might lead to different results when the order is altered. +Example: suppose one need to calculate `1002*99/100*21/100`. Following the left-to-right order, this would result in `1002*99/100*21/100 = 99198/100*21/100 = 991*21/100 = 20811/100 = 208`. If someone did this operation in a different order, let's say `1002*21/100*99/100`, the result wound be `1002*21/100*99/100 = 21042/100*99/100 = 210*99/100 = 20790/100 = 207`. + + +## Potential Mana +*Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. +Every IOTA token, whether storage deposit or not, generates potential Mana. +The view on the potential Mana value can be deterministically derived from the UTXO ledger, +based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the slot index of the transaction). + +### Potential Mana Semantic Validation +- Potential Mana must and can only be consumed when the corresponding output is consumed. +- When the UTXO is spent, the potential Mana is lost, therefore the user must specify what should happen to the accumulated potential Mana value. There are three options: + - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; + - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; + - ignored: generated Mana can be ignored, so that it will be destroyed during the transaction. +- The exact formula of the Potential Mana generated by an output $n$ slots old, holding $\text{Amount}$ IOTA tokens is given by: + $$ + \frac{\text{Generation Rate}}{\beta}\left(1-\exp(-\beta \text{ SlotDuration } n)\right)\text{Amount} + $$ + where $\text{Generation Rate}$, $\text{SlotDuration}$, and $\beta$ are protocol parameters. +- Thus, Potential Mana must be calculated explicitly including decay as follows: + - Let `Consumption Slot`, `Creation Slot` and `Amount` given by the table below + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Amountuint64 + The amount of IOTA tokens held in the output. +
Creation Slotuint64 + The index of slot in which the output was created. +
Consumption Slotuint64 + The index of slot in which the output is consumed. +
+ - Let `n = Consumption Slot - Creation Slot`. With the aid of the lookup table and the algorithm defined in the last section, find `decay(n)`. If `decay(n)>0`: + - Approximate $2^{32}(1 - \exp{(-\beta \text{ SlotDuration } n)})$ by subtracting `2^32-decay(n)`. Since `decay(n)>0`, this value can be stored as a uint32. + - Multiply by an approximation of $\text{Generation Rate}/\beta$. To do so, multiply by `13410781` and subsequently apply a right-shift of 16 bits. The result will be a uint128. + - Finally, multiply the result by `Amount` (which will require 256 bits) and apply a right-shift of 32 bits. + - If `decay(n)=0`: + - Multiply `Amount*13410781` and apply a right-shift of 16 bits. ## Stored Mana *Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA tokens) of Mana that can be transferred within certain rules between different users, @@ -266,7 +332,7 @@ This field represents the amount of stored Mana at the output's creation time un - It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. - Decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. - To calculate decay of stored Mana, the creation time of each output with stored Mana must be contained in transactions. -- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: `Mana Amount * g(Consumption Slot - Creation Slot)`, where +- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: `Mana Amount * decay(Consumption Slot - Creation Slot)`, where @@ -297,7 +363,7 @@ This field represents the amount of stored Mana at the output's creation time un
-And `g(n)` is an approximation of `e^{-beta*SlotDuration*n}`, given by a lookup table. The reason for the use of a lookup table for this calculation is the same as for the Potential Mana calculations. The table used is also the same as for the Potential Mana calculations, given by Lookup Table: Decays for Mana. +And `decay(Consumption Slot - Creation Slot)` is calculated with the lookup table and algorithm defined in section "Mana and fixed point arithmetics", by taking `n = Consumption Slot - Creation Slot`. ## Block Issuance Credit @@ -330,24 +396,14 @@ in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger als - If a block is orphaned, the block will not be included in a commitment, and hence, the balance of BIC of the account that issued the block must be unaffected by that block. - The time of the slot commitment must be used to align the local version of the BIC vector with the objective, committed version. It allows for the global control of the BIC dynamic with a Mana decay function. - - Decreasing the BIC value over time is needed to encourage spending and discourage hoarding of BIC. - - This decrease needs also be applied to the potential and stored Mana (that can be allotted to the account as BIC) so that users cannot gain by, e.g., delaying allotting. + - This decrease is also applied to the potential and stored Mana (that can be allotted to the account as BIC) so users cannot gain by delaying or advancing the allotting. - The balance of the BIC vector at the slot commitment must be the sum of: - The balances of the previous committed BIC vector. - - All Mana allotted as BIC in accepted transactions of the committed slot. -Note that, in the case of only decaying the BIC vector at the end of each epoch, this Mana has to be decayed by a factor proportional to the difference between the transaction slot index and the end of the epoch. + - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of only decaying the BIC vector at the end of each epoch, this Mana would have to be decayed by a factor proportional to the difference between the transaction slot index and the index of the last slot of the epoch. However, since the decays rate is small, this difference will be always smaller than half percent. We understand that this difference (since it's not composable and can only be "taken profit of" once) does not justify the user experience-related issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being allotted in a transaction. - Subtract from BIC all Mana burned by accepted blocks of the committed slots. -- BIC updates (increase, deduction/Mana burning, Mana decay) must happen upon slot commitments. -Note that the implementation can decide to only update the stored BIC value whenever BIC is changed due to allotting or issuance of new blocks -(and decay the BIC value only when one of those events happen). In this case, there is the need to store and commit to the last time the BIC value was decayed. -- Mana decay must be applied at the end of each epoch according to formula: - -```math -\text{BIC}_{i+1} =\text{BIC}_i * g(number of slots per epoch)-\sum \text{Burnt BIC}+\sum \text{Decayed allotted BIC}, -``` - -where $\text{BIC}_i$ is the amount of BIC held by account at the end of the slot commitment `i`, and `g(number of slots per epoch)` is given by Lookup Table: Decays for Mana. - +- BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the end of the epoch. +- Mana decay must be applied at the end of each epoch according to the algorithm: + - Let $\text{BIC}_i$ be the amount of BIC held by account at the end of the slot `i`, which is the last slot of an epoch. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC, by first multiplying it by `4287129767` and subsequently applying a right-shift of 32 bits. If `i` is not the last slot of an epoch, this decay should not be applied. - A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that the account has authorized the block and that Mana can be burned from BIC of that account. @@ -366,8 +422,9 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra - Mana rewards must become available for claiming at slot commitments. - Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. - Mana rewards must be put on outputs as stored Mana on the output side of the transaction. -- Decay must be applied to Mana rewards before they are put on outputs according to the following formula: `Reward * g(Claiming Slot - Commitment Slot)`, where - +- Decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: + - Let `Reward`, `Consumption Slot` and `Creation Slot` be as follows: +
@@ -394,8 +451,11 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra The index of slot in which Mana rewards are claimed. -
Name Type
-and `g(n)` is given by Lookup Table: Decays for Mana. + + - Let `n = Consumption Slot - Creation Slot`. If `n > 0`, with the aid of the lookup table and the algorithm defined in the section "Mana and fixed point arithmetics", find `decay(n)`. + - Multiply `Reward * decay(n)`. This result should be an uint128. Apply a right-shift of 32 bits. This final value can be stored as a uint64. + - If `n = 0`, the amount to be put on outputs is the entire `Reward`. However, this behaviour should not be the usual, since for the rewards to be claimed, the slot has to be committed to. We leave this edge case specified just to prevent bugs or unusual and unforeseen node behaviour. + ## Data Types & Subschema Notation From e80630c0bbdc705c46b4314146169286bba0948c Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 12 Jun 2023 09:08:17 +0100 Subject: [PATCH 020/157] Minor changes --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index eb5990d23..7dc7eba70 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -105,7 +105,7 @@ Applying decay for the generation of new Mana and staking rewards is straightfor Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding behaviour in different architectures. The results of the operations involving floating point variables might difer by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, diferences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviours in the system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. -We introduce in this section a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of $2^{32}\exp(-\beta \text{ SlotDuration } n)$ for different values of $n$: +We introduce in this section a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of $2^{32}\exp(-\beta \text{ SlotDuration } n)$ (where $\beta$ and $\text{SlotDuration}$ are protocol parameters) for different values of $n$: From e1f11b7619a1a201ca2ea3d8de448961d64a9043 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 12 Jun 2023 09:33:27 +0100 Subject: [PATCH 021/157] add missing right-shift to the stored mana --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 7dc7eba70..03445fc34 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -363,7 +363,7 @@ This field represents the amount of stored Mana at the output's creation time un
Lookup Table: Decays for Mana in slot granularity
-And `decay(Consumption Slot - Creation Slot)` is calculated with the lookup table and algorithm defined in section "Mana and fixed point arithmetics", by taking `n = Consumption Slot - Creation Slot`. +And `decay(Consumption Slot - Creation Slot)` is calculated with the lookup table and algorithm defined in section "Mana and fixed point arithmetics", by taking `n = Consumption Slot - Creation Slot`. After that, a right-shift of 32 bits must be applied. ## Block Issuance Credit From 8c0acd5b552b1835b5272b872a9660c00ba3f6c0 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Mon, 12 Jun 2023 18:13:37 +0200 Subject: [PATCH 022/157] Fixed formula rendering until Potential Mana section --- tips/TIP-0039/tip-0039.md | 70 ++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 03445fc34..d668c8359 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -37,12 +37,12 @@ requires: TIP-42 - [Copyright](#copyright) # Summary -This document defines the Mana related concepts and the Mana dynamics in the IOTA 2.0 protocol. +This document defines the Mana-related concepts and the Mana dynamics in the IOTA 2.0 protocol. The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana,** as well as the **Block Issuance Credit (BIC)** that Mana can be allotted to. # Motivation -Mana is a resource used to determine the allowed throughput of a user and as a payment form for the block issuance in the Mana burn mechanism. -Mana can be obtained by actions helpful and profitable for the network, like token holding or engagement in securing the network. Additionally, it is necessary to use the network, so it plays the core role in the IOTA tokenomics. Following document gives a high level overview of Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of Mana is burned in each block which is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to their account to increase their BIC and ensure it does not go negative. In order to issue blocks, allot Mana and use fully all the Mana functionalities, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). +Mana is a resource used to determine the allowed throughput of a user and as a payment form for block issuance in the Mana burn mechanism. +Mana can be obtained by actions helpful and profitable for the network, like token holding or engagement in securing the network. Additionally, it is necessary to use the network, so it plays the core role in the IOTA tokenomics. The following document gives a high-level overview of Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation, and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of Mana is burned in each block, which is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to their account to increase their BIC and ensure it does not go negative. In order to issue blocks, allot Mana, and fully use all the Mana functionalities, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). # Building Blocks @@ -58,15 +58,15 @@ It is an essential element of the IOTA protocol, as it is used to: * as a payment form for the block issuance. The following solutions are designed around the newest IOTA Congestion Control Algorithm (ICCA) with Mana Credits. -Additionally, Mana implementation is strictly connected to the accounts introduced in [TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivation scheme. +Additionally, Mana implementation is strictly connected to the accounts introduced in [TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivization scheme. **Mana** can have different forms, each of which is described in the following sections. * [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved within certain rules between the different owners, which allows for Mana market development. * [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. -* When user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit form, -mentioned before stored Mana and storing the resource directly in the UTXO ledger, or user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). +* When the user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit form, +mentioned before stored Mana, and store the resource directly in the UTXO ledger, or the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). * [**Mana rewards**](#mana-rewards) is another form of Mana used to reward for participation in staking for validation and delegating IOTA tokens. The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. @@ -76,17 +76,17 @@ According to the congestion control mechanism, during each block issuance, the b ### Reference Mana Cost *Reference Mana Cost (RMC)* is used to decide upon commitment how much Mana is burned from BIC by each block in that slot. -RMC is computed according to an algorithm based on recent traffic activity: the algorithm counts the number of blocks in slots which are *Maximum Committable Age (MCA)* slots in the past, +RMC is computed according to an algorithm based on recent traffic activity: the algorithm counts the number of blocks in slots that are *Maximum Committable Age (MCA)* slots in the past so that all nodes agree on that value of RMC. -From the high-level perspective, the RMC algorithm works as follows: +From a high-level perspective, the RMC algorithm works as follows: - If the number of blocks in slot `i-MCA` is larger than a given threshold, then the RMC increases. - Otherwise, if the activity is low, the RMC decreases. - The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes too large for the majority of users, and activity drops. The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid price manipulations by malicious actors. -Note that blocks from issuers with negative BIC balance are excluded with respect to the RMC calculation, but they do make part of the slot commitment. -To limit fluctuations in the RMC, it is proposed to update its value every MCA slots at least. +Note that blocks from issuers with negative BIC balances are excluded with respect to the RMC calculation, but they do make part of the slot commitment. +To limit fluctuations in the RMC, it is proposed to update its value every MCA slot at least. ## Mana decay Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. To guarantee non-gameability (any certain behavior, e.g., @@ -97,15 +97,15 @@ splitting accounts, cannot be profitable for the user) and the fairness of Mana, - Mana bound to accounts for block issuance ([Block Issuance Credit](#block-issuance-credit)); - Mana rewarded for staking and delegation ([Mana rewards](#mana-rewards)). -As the form in which the decay factor will be applied might differ between the Mana types, it is essential to point out that all of them are based on the same exponential decay, with the same parameter $\beta$. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. +As the form in which the decay factor will be applied might differ between the Mana types, it is essential to point out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. -Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on slot indices, not local times. For block issuance credit, it is advised applying the decay function in a slot-based manner and updating it upon slot commitment. +Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on slot indices, not local times. For block issuance credit, it is advised to apply the decay function in a slot-based manner and update it upon slot commitment. ## Mana and fixed point arithmetics -Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding behaviour in different architectures. The results of the operations involving floating point variables might difer by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, diferences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviours in the system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. +Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding behavior in different architectures. The results of the operations involving floating point variables might differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, differences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviors in the system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. -We introduce in this section a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of $2^{32}\exp(-\beta \text{ SlotDuration } n)$ (where $\beta$ and $\text{SlotDuration}$ are protocol parameters) for different values of $n$: +We introduce in this section a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^32 * exp(-β * Slot Duration * n)`, where `β` and `Slot Duration` are protocol parameters, for different values of `n`: @@ -233,34 +233,36 @@ We introduce in this section a lookup table that will be used in the rest of thi ### How to use the lookup table -The table defined above only gives the values of `decay(n)` for some selected values of $n$ in the form of powers of 2. To calculate `decay(n)` for other $n$'s, we combine values of given $n$ using the following algorithm: +The table defined above only gives the values of `decay(n)` for some selected values of `n` in the form of powers of `2`. To calculate `decay(n)` for other `n`, we combine values of given `n` using the following algorithm: -- If $0> 32 - ``` +``` +value = uint64(2^32) +for k = 22,...,0: + if (ck == 1): + value = [value * decay(2^k)] >> 32 +``` - If $n\geq 2^{23}$: Let $\sum_{k=0}^{K}c_k 2^k=n$, i.e., let $(c_{K}, c_{K-1},...,c_1,c_0)$ be the binary representation of $n$. Let $m$ be the decimal representation of $(c_{K}, c_{K-1},...,c_{23},c_{22})$. +- If `n ≥ 2^23`: Let `sum(c_k * 2^k) = n, k = 0,...,K`, i.e., let `(c_K, c_{K-1}, ..., c_1, c_0)` be the binary representation of `n`. +Let `m` be the decimal representation of `(c_K, c_{K-1}, ..., c_23, c_22)`. - ``` - value = uint64(2^32) - for i = 1,...,m: - value = [value*decay(2^22)] >> 32 - for k = 21,...,0: - if (ck == 1): - value = [value*decay(2^k)] >> 32 - ``` +``` +value = uint64(2^32) +for i = 1,...,m: + value = [value * decay(2^22)] >> 32 +for k = 21,...,0: + if (ck == 1): + value = [value * decay(2^k)] >> 32 +``` - Notice that since the values in the table are type uint32, the multiplications in the algorithm have to be done using a uint64 variable to avoid overflowing. The final result can be stored as a uint32 value (if needed), since after the shift operation the result will be smaller than $2^{32}$. +Notice that since the values in the table are type `uint32`, the multiplications in the algorithm have to be done using a `uint64` variable to avoid overflowing. The final result can be stored as a `uint32` value (if needed), since after the shift operation the result will be smaller than `2^32`. -- If $n=0$, $\exp(-\beta \text{ SlotDuration } n)=1$. Thus, in this case, the decay (and the lookup table) should not be applied. +- If `n = 0`, `exp(-β * Slot Duration * n) = 1`. Thus, in this case, the decay (and the lookup table) should not be applied. -Other implementations of the fuction are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial, since sequences of divisions and multiplications with integers might lead to different results when the order is altered. -Example: suppose one need to calculate `1002*99/100*21/100`. Following the left-to-right order, this would result in `1002*99/100*21/100 = 99198/100*21/100 = 991*21/100 = 20811/100 = 208`. If someone did this operation in a different order, let's say `1002*21/100*99/100`, the result wound be `1002*21/100*99/100 = 21042/100*99/100 = 210*99/100 = 20790/100 = 207`. +Other implementations of the function are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and multiplications with integers might lead to different results when the order is altered. +Example: suppose one needs to calculate `1002*99/100*21/100`. Following the left-to-right order, this would result in `1002*99/100*21/100 = 99198/100*21/100 = 991*21/100 = 20811/100 = 208`. If someone did this operation in a different order, let's say `1002*21/100*99/100`, the result would be `1002*21/100*99/100 = 21042/100*99/100 = 210*99/100 = 20790/100 = 207`. ## Potential Mana From 0fcad4ade17b2f0c61a78d1b369990df93c4a35a Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Mon, 12 Jun 2023 18:17:06 +0200 Subject: [PATCH 023/157] Minor corrections --- tips/TIP-0039/tip-0039.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index d668c8359..db1c83362 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -80,7 +80,7 @@ RMC is computed according to an algorithm based on recent traffic activity: the so that all nodes agree on that value of RMC. From a high-level perspective, the RMC algorithm works as follows: -- If the number of blocks in slot `i-MCA` is larger than a given threshold, then the RMC increases. +- If the number of blocks in slot `i - MCA` is larger than a given threshold, then the RMC increases. - Otherwise, if the activity is low, the RMC decreases. - The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes too large for the majority of users, and activity drops. @@ -244,7 +244,6 @@ for k = 22,...,0: value = [value * decay(2^k)] >> 32 ``` -- If $n\geq 2^{23}$: Let $\sum_{k=0}^{K}c_k 2^k=n$, i.e., let $(c_{K}, c_{K-1},...,c_1,c_0)$ be the binary representation of $n$. Let $m$ be the decimal representation of $(c_{K}, c_{K-1},...,c_{23},c_{22})$. - If `n ≥ 2^23`: Let `sum(c_k * 2^k) = n, k = 0,...,K`, i.e., let `(c_K, c_{K-1}, ..., c_1, c_0)` be the binary representation of `n`. Let `m` be the decimal representation of `(c_K, c_{K-1}, ..., c_23, c_22)`. From e55b18ef783f192ebe09e64a245b7da883b9084d Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Wed, 14 Jun 2023 12:35:28 +0200 Subject: [PATCH 024/157] Finish fixing formulas rendering --- tips/TIP-0039/tip-0039.md | 58 +++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index db1c83362..68a96bc30 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -272,15 +272,13 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX ### Potential Mana Semantic Validation - Potential Mana must and can only be consumed when the corresponding output is consumed. -- When the UTXO is spent, the potential Mana is lost, therefore the user must specify what should happen to the accumulated potential Mana value. There are three options: +- When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the accumulated potential Mana value. There are three options: - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; - - ignored: generated Mana can be ignored, so that it will be destroyed during the transaction. -- The exact formula of the Potential Mana generated by an output $n$ slots old, holding $\text{Amount}$ IOTA tokens is given by: - $$ - \frac{\text{Generation Rate}}{\beta}\left(1-\exp(-\beta \text{ SlotDuration } n)\right)\text{Amount} - $$ - where $\text{Generation Rate}$, $\text{SlotDuration}$, and $\beta$ are protocol parameters. + - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. +- The exact formula of the Potential Mana generated by an output `n` slots old, holding `Amount` IOTA tokens, is given by: + `Generation Rate * Amount * (1 - exp(-β * Slot Duration * n)) / β` + where `Generation Rate`, `Slot Duration`, and `β` are protocol parameters. - Thus, Potential Mana must be calculated explicitly including decay as follows: - Let `Consumption Slot`, `Creation Slot` and `Amount` given by the table below
Lookup Table: Decays for Mana in slot granularity
@@ -311,12 +309,13 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX
- - Let `n = Consumption Slot - Creation Slot`. With the aid of the lookup table and the algorithm defined in the last section, find `decay(n)`. If `decay(n)>0`: - - Approximate $2^{32}(1 - \exp{(-\beta \text{ SlotDuration } n)})$ by subtracting `2^32-decay(n)`. Since `decay(n)>0`, this value can be stored as a uint32. - - Multiply by an approximation of $\text{Generation Rate}/\beta$. To do so, multiply by `13410781` and subsequently apply a right-shift of 16 bits. The result will be a uint128. + - Let `n = Consumption Slot - Creation Slot`. With the aid of the lookup table and the algorithm defined in the last section, find `decay(n)`. If `decay(n) > 0`: + - Approximate `2^32 * (1 - exp(-β * Slot Duration * n))` by subtracting `2^32 - decay(n)`. Since `decay(n) > 0`, this value can be stored as a `uint32`. + - Multiply by an approximation of `Generation Rate / β`. To do so, multiply by `13410781` and subsequently apply a right-shift of 16 bits. The result will be a `uint128`. - Finally, multiply the result by `Amount` (which will require 256 bits) and apply a right-shift of 32 bits. - - If `decay(n)=0`: - - Multiply `Amount*13410781` and apply a right-shift of 16 bits. + - If `decay(n) = 0`: + - Multiply `Amount * 13410781` and apply a right-shift of 16 bits. + ## Stored Mana *Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA tokens) of Mana that can be transferred within certain rules between different users, @@ -331,8 +330,8 @@ This field represents the amount of stored Mana at the output's creation time un - Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be spent within a block. It must be allotted to an account's BIC in order to pay for Mana burned by blocks. - *Mana Sales Outputs* must be used for transferring stored or potential Mana freely from one account to another. - It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. -- Decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. -- To calculate decay of stored Mana, the creation time of each output with stored Mana must be contained in transactions. +- The decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. +- To calculate the decay of stored Mana, the creation time of each output with stored Mana must be contained in transactions. - The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: `Mana Amount * decay(Consumption Slot - Creation Slot)`, where @@ -364,12 +363,13 @@ This field represents the amount of stored Mana at the output's creation time un
-And `decay(Consumption Slot - Creation Slot)` is calculated with the lookup table and algorithm defined in section "Mana and fixed point arithmetics", by taking `n = Consumption Slot - Creation Slot`. After that, a right-shift of 32 bits must be applied. +And `decay(Consumption Slot - Creation Slot)` is calculated with the lookup table and algorithm defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) +by taking `n = Consumption Slot - Creation Slot`. After that, a right-shift of 32 bits must be applied. ## Block Issuance Credit *Block Issuance Credit (BIC)* Mana is used for congestion control, i.e., to pay for blocks to be scheduled and gossiped around the network and seen by everyone. -Congestion control manages which blocks should be gossiped to neighbours based on Mana burned from the block issuance credits by the block. +Congestion control manages which blocks should be gossiped to neighbors based on Mana burned from the block issuance credits by the block. It is important to distinguish between **blocks** and **transactions**: congestion control only deals with blocks, which are the containers that carry transactions around the network. It does not care about the transactions inside the blocks. @@ -380,34 +380,34 @@ This is why Mana cannot be burned from BIC by a transaction, it can only be burn ![](./img/gFLB1Ms.png) ### Block Issuance Credit Semantic Validation -- Block issuance credits must stored on a per-account basis. +- Block issuance credits must be stored on a per-account basis. - Accounts must be represented by _Account Outputs_ on the UTXO ledger. The cost of permanently storing any outputs (until destruction) in the ledger is covered by the _storage deposit_. Because of that, the number of accounts is capped at a number proportional to the max supply of tokens, contrary to the number of plain addresses. Because BIC must be tracked in slot commitments, keeping the number of entries (even though the user can create multiple accounts) in that data structure as small as possible is desirable. Using account IDs for that purpose is thus a good fit. -- It is not possible to store BIC without an Account Output because Mana burned by blocks must also be deducted from BIC and the block cannot modify the Account Output. +- It is not possible to store BIC without an Account Output because Mana burned by blocks must also be deducted from BIC, and the block cannot modify the Account Output. Consequently, the ledger state is not bloated by having to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that requires a storage deposit in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the block issuance credits. - A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. - The end time of an epoch is used for the decay calculation at the end of each epoch. - - Definition of slots based on time of the genesis slot and a slot duration. - - The commitment mechanism per slot is needed to ensure the unified perception of the BIC in the longer run. + - Definition of slots based on the time of the genesis slot and slot duration. + - A commitment mechanism per slot is needed to ensure the unified perception of the BIC in the longer run. - The global agreement on the BIC balances among all the nodes is required. - - It can be achieved by including the BIC vector to the slot commitments. This guarantees that all nodes have the same perception of the BIC balances from a certain point in time. + - It can be achieved by including the BIC vector in the slot commitments. This guarantees that all nodes have the same perception of the BIC balances from a certain point in time. - If a block is orphaned, the block will not be included in a commitment, and hence, the balance of BIC of the account that issued the block must be unaffected by that block. - The time of the slot commitment must be used to align the local version of the BIC vector with the objective, committed version. It allows for the global control of the BIC dynamic with a Mana decay function. - This decrease is also applied to the potential and stored Mana (that can be allotted to the account as BIC) so users cannot gain by delaying or advancing the allotting. - The balance of the BIC vector at the slot commitment must be the sum of: - - The balances of the previous committed BIC vector. - - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of only decaying the BIC vector at the end of each epoch, this Mana would have to be decayed by a factor proportional to the difference between the transaction slot index and the index of the last slot of the epoch. However, since the decays rate is small, this difference will be always smaller than half percent. We understand that this difference (since it's not composable and can only be "taken profit of" once) does not justify the user experience-related issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being allotted in a transaction. + - The balances of the previously committed BIC vector. + - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of only decaying the BIC vector at the end of each epoch, this Mana would have to be decayed by a factor proportional to the difference between the transaction slot index and the index of the last slot of the epoch. However, since the decay rate is small, this difference will be always smaller than half a percent. We understand that this difference (since it's not composable and can only be "taken profit of" once) does not justify the user experience-related issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being allotted in a transaction. - Subtract from BIC all Mana burned by accepted blocks of the committed slots. - BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the end of the epoch. - Mana decay must be applied at the end of each epoch according to the algorithm: - - Let $\text{BIC}_i$ be the amount of BIC held by account at the end of the slot `i`, which is the last slot of an epoch. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC, by first multiplying it by `4287129767` and subsequently applying a right-shift of 32 bits. If `i` is not the last slot of an epoch, this decay should not be applied. + - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an epoch. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC, by first multiplying it by `4287129767` and subsequently applying a right-shift of 32 bits. If `i` is not the last slot of an epoch, this decay should not be applied. - A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that -the account has authorized the block and that Mana can be burned from BIC of that account. +the account has authorized the block and that Mana can be burned from the BIC of that account. - The issuer must specify the maximum amount of Mana they will allow to be burned from BIC. - In the above-mentioned permission, the account owner must commit to a certain maximum amount of Mana that will be burned from BIC. - The declared burning amount must be at least the required burning for the current slot. @@ -423,7 +423,7 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra - Mana rewards must become available for claiming at slot commitments. - Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. - Mana rewards must be put on outputs as stored Mana on the output side of the transaction. -- Decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: +- The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: - Let `Reward`, `Consumption Slot` and `Creation Slot` be as follows: @@ -453,9 +453,9 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra
- - Let `n = Consumption Slot - Creation Slot`. If `n > 0`, with the aid of the lookup table and the algorithm defined in the section "Mana and fixed point arithmetics", find `decay(n)`. - - Multiply `Reward * decay(n)`. This result should be an uint128. Apply a right-shift of 32 bits. This final value can be stored as a uint64. - - If `n = 0`, the amount to be put on outputs is the entire `Reward`. However, this behaviour should not be the usual, since for the rewards to be claimed, the slot has to be committed to. We leave this edge case specified just to prevent bugs or unusual and unforeseen node behaviour. + - Let `n = Consumption Slot - Creation Slot`. If `n > 0`, with the aid of the lookup table and the algorithm defined in the section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), find `decay(n)`. + - Multiply `Reward * decay(n)`. This result should be a `uint128`. Apply a right-shift of 32 bits. This final value can be stored as a `uint64`. + - If `n = 0`, the amount to be put on outputs is the entire `Reward`. However, this behavior should not be the usual, since for the rewards to be claimed, the slot has to be committed to. We leave this edge case specified just to prevent bugs or unusual and unforeseen node behavior. ## Data Types & Subschema Notation From 25876259796577ef62ab6f03a6137d8f58160e85 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Wed, 14 Jun 2023 12:39:59 +0200 Subject: [PATCH 025/157] Minor correction --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 68a96bc30..a71c2f7ee 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -277,7 +277,7 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. - The exact formula of the Potential Mana generated by an output `n` slots old, holding `Amount` IOTA tokens, is given by: - `Generation Rate * Amount * (1 - exp(-β * Slot Duration * n)) / β` + `Generation Rate * Amount * (1 - exp(-β * Slot Duration * n)) / β`, where `Generation Rate`, `Slot Duration`, and `β` are protocol parameters. - Thus, Potential Mana must be calculated explicitly including decay as follows: - Let `Consumption Slot`, `Creation Slot` and `Amount` given by the table below From ecfe75b10926670038db121bfaa6bbcc3e1b7699 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 18 Jun 2023 22:07:18 +0100 Subject: [PATCH 026/157] change to decay indices --- tips/TIP-0039/tip-0039.md | 217 ++++++++++++++++++++++++++++---------- 1 file changed, 159 insertions(+), 58 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index a71c2f7ee..8e407dfe9 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -99,13 +99,15 @@ splitting accounts, cannot be profitable for the user) and the fairness of Mana, As the form in which the decay factor will be applied might differ between the Mana types, it is essential to point out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. -Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on slot indices, not local times. For block issuance credit, it is advised to apply the decay function in a slot-based manner and update it upon slot commitment. +Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on decay indices, not local times. Every`8192` slots, the decay index changes, meaning that every set of consecutive `2^(13)` slots will have the same decay index. + +The decay parameter `β` (together with the Mana generation parameter) were set so the maximum theoretical Mana in the system is `2^53-1`. This means that, even though Mana is stored as a int64, it effectively uses 54 bits (53 for the value and one for the sign). Notice that this value of `2^53-1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^53-1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. ## Mana and fixed point arithmetics Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding behavior in different architectures. The results of the operations involving floating point variables might differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, differences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviors in the system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. -We introduce in this section a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^32 * exp(-β * Slot Duration * n)`, where `β` and `Slot Duration` are protocol parameters, for different values of `n`: +We introduce in this section a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^12 * exp(-β * Decay Index Duration * n)`, where `β` and `Decay Index Duration` are protocol parameters, for different values of `n`: @@ -233,55 +235,105 @@ We introduce in this section a lookup table that will be used in the rest of thi ### How to use the lookup table -The table defined above only gives the values of `decay(n)` for some selected values of `n` in the form of powers of `2`. To calculate `decay(n)` for other `n`, we combine values of given `n` using the following algorithm: +==TO DO: decide to max decay index in the table== -- If `0 < n < 2^23`: Let `sum(c_k * 2^k) = n, k = 0,...,22`, i.e., let `(c_22, c_21, ..., c_1, c_0)` be the binary representation of `n`. - -``` -value = uint64(2^32) -for k = 22,...,0: - if (ck == 1): - value = [value * decay(2^k)] >> 32 -``` +The table defined above only gives the values of `decay(n)` for some values of `n` up to 365. To calculate `decay(n)` for larger values of `n`, we combine values of given `n` using the following algorithm: -- If `n ≥ 2^23`: Let `sum(c_k * 2^k) = n, k = 0,...,K`, i.e., let `(c_K, c_{K-1}, ..., c_1, c_0)` be the binary representation of `n`. -Let `m` be the decimal representation of `(c_K, c_{K-1}, ..., c_23, c_22)`. +- If `n > 365`: Let `n/365` be an integer division (e.g., `367/365 = 1`) and `n mod 365` be the module operation (e.g., `367 mod 365 = 2`). ``` -value = uint64(2^32) -for i = 1,...,m: - value = [value * decay(2^22)] >> 32 -for k = 21,...,0: - if (ck == 1): - value = [value * decay(2^k)] >> 32 +value = uint32(2^12) +for i = 1,...,n/365: + value = [value * decay(365)] >> 12 +value = [value * decay(n mod 365)] >> 12 ``` -Notice that since the values in the table are type `uint32`, the multiplications in the algorithm have to be done using a `uint64` variable to avoid overflowing. The final result can be stored as a `uint32` value (if needed), since after the shift operation the result will be smaller than `2^32`. +Notice that since the values in the table smaller than `2^12`, the multiplications in the algorithm have to be done using a `uint32` variable to avoid overflowing. The final result can be stored as a `uint16` value (if needed), since after the final shift operation the result will be smaller than `2^12` again. -- If `n = 0`, `exp(-β * Slot Duration * n) = 1`. Thus, in this case, the decay (and the lookup table) should not be applied. +- If `n = 0`, `exp(-β * Decay Index Duration * n) = 1`. Thus, in this case, the decay (and the lookup table) should not be applied. Other implementations of the function are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and multiplications with integers might lead to different results when the order is altered. Example: suppose one needs to calculate `1002*99/100*21/100`. Following the left-to-right order, this would result in `1002*99/100*21/100 = 99198/100*21/100 = 991*21/100 = 20811/100 = 208`. If someone did this operation in a different order, let's say `1002*21/100*99/100`, the result would be `1002*21/100*99/100 = 21042/100*99/100 = 210*99/100 = 20790/100 = 207`. + ## Potential Mana *Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not, generates potential Mana. The view on the potential Mana value can be deterministically derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the slot index of the transaction). +### Rationale behind the Potential Mana formulas + +We model the potential Mana generated by an output holding `amount` IOTA tokens as the combination of a fixed generation per slot `generation_per_slot * amount` and a decay equivalent to a multiplication by `2^(-12)*decay(1)` everytime a decay index ends. + +![](https://hackmd.io/_uploads/Bkzz3PiD2.png) + + +Let `i` be the decay index of the creation slot and `j` be the decay index of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in decay index `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in decay index `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n- 1` times, and so on, until the Mana generated in decay index `j`, which is not decayed at all. Adding these values, we find the following formulas: + +- If `n > 1`: + `Potential_Mana = amount * generation_per_slot (d1*decay(n)*2^(-12) + d2 + slots_per_decay_index * decay(1)*(1-decay(n-1)*2^(-12))/(2^(12)-decay(1)))` +- If `n = 1`: + `Potential_Mana = amount * generation_per_slot (d1*decay(1)*2^(-12) + d2)` +- If `n = 0`: + `Potential_Mana = amount * generation_per_slot * (d1+d2)` + + where + - `slots_per_decay_index` is the number of slot in an epoch , i.e., `8192` + - `d1 = slot_after_decay_index_i - creation_slot` + - `slot_after_decay_index_i` is the first slot of the decay index `i + 1` ; + - `d2 = consumption_slot - first_slot_decay_index_j` + - `first_slot_decay_index_j` is the first slot of decay index `j` ; + - `generation_per_slot = 2^(-3)` is the Mana generated by holding 1 IOTA for 1 slot. + + +The exact order of the operations that must be done are defined in the next section. + + ### Potential Mana Semantic Validation - Potential Mana must and can only be consumed when the corresponding output is consumed. - When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the accumulated potential Mana value. There are three options: - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. -- The exact formula of the Potential Mana generated by an output `n` slots old, holding `Amount` IOTA tokens, is given by: - `Generation Rate * Amount * (1 - exp(-β * Slot Duration * n)) / β`, - where `Generation Rate`, `Slot Duration`, and `β` are protocol parameters. -- Thus, Potential Mana must be calculated explicitly including decay as follows: - - Let `Consumption Slot`, `Creation Slot` and `Amount` given by the table below -
Lookup Table: Decays for Mana in slot granularity
+- The exact algorithm to calculate the Potential Mana generated by an output created at slot `creation_slot` (which has a decay index `creation_decay_index`) and consumed at slot `consumption_slot` (which has a decay index `consumption_decay_index`), holding `Amount` IOTA tokens, is given by (again, in the pseudocode below, `slot_after_creation_decay_index` is the first slot of the decay index after the creation decay index and `first_slot_consumption_decay_index` is the first slot of the consumption decay index): + ==to do: fix the operations below so it does not overflow== + +``` +if creation_decay_index == consumption_decay_index: + maxAmountValueToScale = uint64(2^51-1) + bitsDecreased := 0 + while amount > uint64(maxAmountValueToScale) { + amount = amount >> 1 + bitsDecreased++ + } + + potential_mana = amount * (consumption_slot - creation_slot) + potential_mana = potential_mana >> 3 - bitsDecreased + + +elif creation_decay_index + 1 == consumption_decay_index: + d1 = slot_after_creation_decay_index - creation_slot + d2 = consumption_slot - first_slot_consumption_decay_index + maxAmountValueToScale = uint64(2^51-1) + bitsDecreased := 0 + while amount > uint64(maxAmountValueToScale) { + amount = amount >> 1 + bitsDecreased++ + } + + potential_mana = amount * (d1*1023 + d2*1024) *2^(-(13- bitsDecreased)) + +else: + d1 = slot_after_creation_decay_index - creation_slot + d2 = consumption_slot - first_slot_consumption_decay_index + potential_mana = amount *2^(-3) * 2^(-12)(d1*decay(n) + 4096 d2 +8380416*(4096-decay(n-1))) + + +``` + +
@@ -309,17 +361,10 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX
Name Type
- - Let `n = Consumption Slot - Creation Slot`. With the aid of the lookup table and the algorithm defined in the last section, find `decay(n)`. If `decay(n) > 0`: - - Approximate `2^32 * (1 - exp(-β * Slot Duration * n))` by subtracting `2^32 - decay(n)`. Since `decay(n) > 0`, this value can be stored as a `uint32`. - - Multiply by an approximation of `Generation Rate / β`. To do so, multiply by `13410781` and subsequently apply a right-shift of 16 bits. The result will be a `uint128`. - - Finally, multiply the result by `Amount` (which will require 256 bits) and apply a right-shift of 32 bits. - - If `decay(n) = 0`: - - Multiply `Amount * 13410781` and apply a right-shift of 16 bits. - + ## Stored Mana -*Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA tokens) of Mana that can be transferred within certain rules between different users, -which allows for Mana market development. +*Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA tokens) of Mana that can be transferred within certain rules between different users, which allows for Mana market development. All output types except Foundry Outputs can hold stored Mana in the *Mana Amount* field. This field represents the amount of stored Mana at the output's creation time until the time when the output is consumed without decay being applied to it. @@ -332,9 +377,10 @@ This field represents the amount of stored Mana at the output's creation time un - It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. - The decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. - To calculate the decay of stored Mana, the creation time of each output with stored Mana must be contained in transactions. -- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: `Mana Amount * decay(Consumption Slot - Creation Slot)`, where +- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: + - Let `Mana Amount`, `Consumption Slot`, and `Creation Slot`, be - +
@@ -361,11 +407,28 @@ This field represents the amount of stored Mana at the output's creation time un The index of slot in which the output is consumed. -
Name Type
- -And `decay(Consumption Slot - Creation Slot)` is calculated with the lookup table and algorithm defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) -by taking `n = Consumption Slot - Creation Slot`. After that, a right-shift of 32 bits must be applied. + + + The algorithm to decay the stored Mana is as follows +``` +creation_decay_index = decay_index(creation_slot) +consumption_decay_index = decay_index(consumption_slot) +if creation_decay_index == consumption_decay_index: + new_mana_amount = mana_amount + +else: + maxManaValueToScale = uint64(2^52-1) + bitsDecreased := 0 + while mana_amount > uint64(maxManaValueToScale) { + mana_amount = mana_amount >> 1 + bitsDecreased++ + } + + new_mana_amount = mana_amount * decay(consumption_decay_index - creation_decay_index) + new_mana_amount = new_mana_amount >> (12 - bitsDecreased) +``` + ## Block Issuance Credit *Block Issuance Credit (BIC)* Mana is used for congestion control, i.e., to pay for blocks to be scheduled and gossiped around the network and seen by everyone. @@ -389,7 +452,7 @@ Using account IDs for that purpose is thus a good fit. Consequently, the ledger state is not bloated by having to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that requires a storage deposit in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the block issuance credits. - A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. - - The end time of an epoch is used for the decay calculation at the end of each epoch. + - The end time of an decay index is used for the decay calculations. - Definition of slots based on the time of the genesis slot and slot duration. - A commitment mechanism per slot is needed to ensure the unified perception of the BIC in the longer run. - The global agreement on the BIC balances among all the nodes is required. @@ -400,11 +463,29 @@ It allows for the global control of the BIC dynamic with a Mana decay function. - This decrease is also applied to the potential and stored Mana (that can be allotted to the account as BIC) so users cannot gain by delaying or advancing the allotting. - The balance of the BIC vector at the slot commitment must be the sum of: - The balances of the previously committed BIC vector. - - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of only decaying the BIC vector at the end of each epoch, this Mana would have to be decayed by a factor proportional to the difference between the transaction slot index and the index of the last slot of the epoch. However, since the decay rate is small, this difference will be always smaller than half a percent. We understand that this difference (since it's not composable and can only be "taken profit of" once) does not justify the user experience-related issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being allotted in a transaction. + - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of only decaying the BIC vector at the end of each decay index, this Mana would have to be decayed by a factor proportional to the difference between the transaction slot index and the index of the last slot of the decay index. However, since the decay rate is small, this difference will be always smaller than half a percent. We understand that this difference (since it's not composable and can only be "taken profit of" once) does not justify the user experience-related issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being allotted in a transaction. - Subtract from BIC all Mana burned by accepted blocks of the committed slots. -- BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the end of the epoch. -- Mana decay must be applied at the end of each epoch according to the algorithm: - - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an epoch. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC, by first multiplying it by `4287129767` and subsequently applying a right-shift of 32 bits. If `i` is not the last slot of an epoch, this decay should not be applied. +- BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the end of the decay index. +- Mana decay must be applied at the end of decay index according to the algorithm: + - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an decay index. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC, by applying: +``` +if BIC > 0: + maxBICValueToScale = int64(2^51-1) + bitsDecreased := 0 + while BIC > maxBICValueToScale { + BIC = BIC >> 1 + bitsDecreased++ + } + new_BIC = BIC * decay(1) + new_BIC = new_BIC >> (12 - bitsDecreased) +else: + new_BIC = BIC + +``` + +If `i` is not the last slot of athe decay index, this decay should not be applied. + + - A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that the account has authorized the block and that Mana can be burned from the BIC of that account. @@ -419,12 +500,12 @@ the account has authorized the block and that Mana can be burned from the BIC of Rewarding validators and delegators with Mana is reasonable as it does not extract value from other IOTA token holders. ### Mana Rewards Semantic Validation -- Mana rewards must be calculated on a per-slot basis. -- Mana rewards must become available for claiming at slot commitments. +- Mana rewards must be calculated on a per-epoch basis. +- Mana rewards must become available for claiming when the last slot of the epoch is committed to. - Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. - Mana rewards must be put on outputs as stored Mana on the output side of the transaction. - The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: - - Let `Reward`, `Consumption Slot` and `Creation Slot` be as follows: + - Let `Reward`, `Reward Epoch`, `Reward Decay Index` and `Claiming Slot Decay Index` be as follows: @@ -435,27 +516,47 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra - + + + + + + - +
NameReward uint64 - The amount of Mana rewards available to be claimed for staking or delegation for a specific slot. + The amount of Mana rewards available to be claimed for staking or delegation for a specific epoch.
Commitment SlotRewards Epoch uint64 - The index of slot in which that specific slot, for which Mana rewards are claimed, was committed. + The index of the epoch for which Mana rewards are claimed. +
Reward Decay Indexuint64 + The decay index of the last slot in Rewards Epoch.
Claiming SlotClaiming Slot Decay Index uint64 - The index of slot in which Mana rewards are claimed. + The decay index of the slot in which the Mana rewards are claimed.
- - Let `n = Consumption Slot - Creation Slot`. If `n > 0`, with the aid of the lookup table and the algorithm defined in the section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), find `decay(n)`. - - Multiply `Reward * decay(n)`. This result should be a `uint128`. Apply a right-shift of 32 bits. This final value can be stored as a `uint64`. - - If `n = 0`, the amount to be put on outputs is the entire `Reward`. However, this behavior should not be the usual, since for the rewards to be claimed, the slot has to be committed to. We leave this edge case specified just to prevent bugs or unusual and unforeseen node behavior. + + - Let `n = Claiming Slot Decay Index - Reward Decay Index`. If `n > 0`, with the aid of the lookup table and the algorithm defined in the section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the rewards, by applying: + + + ``` + maxRewardValueToScale = int64(2^52) + bitsDecreased := 0 + while Reward > maxRewardValueToScale { + Reward = Reward >> 1 + bitsDecreased++ + } + Reward = Reward * decay(n) + Reward = Reward >> (12 - bitsDecreased) + ``` + - If `n = 0`, the amount to be put on outputs is the entire `Reward`. + ## Data Types & Subschema Notation From 14a1ab3d5cb2bf35b7ec0d8db057cc692621da6e Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 19 Jun 2023 10:22:28 +0100 Subject: [PATCH 027/157] minor changes --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 8e407dfe9..3dc4afbf7 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -42,7 +42,7 @@ The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Ma # Motivation Mana is a resource used to determine the allowed throughput of a user and as a payment form for block issuance in the Mana burn mechanism. -Mana can be obtained by actions helpful and profitable for the network, like token holding or engagement in securing the network. Additionally, it is necessary to use the network, so it plays the core role in the IOTA tokenomics. The following document gives a high-level overview of Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation, and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of Mana is burned in each block, which is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to their account to increase their BIC and ensure it does not go negative. In order to issue blocks, allot Mana, and fully use all the Mana functionalities, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). +Mana can be obtained by helpful and profitable actions for the network, like token holding or engagement in securing the network. Additionally, owning Mana is necessary to use the network by issuing blocks, so it plays the core role in the IOTA tokenomics. The following document gives a high-level overview of Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation, and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of Mana is burned in each block, which is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to their account to increase their BIC and ensure it does not go negative. In order to issue blocks, allot Mana, and fully use all the Mana functionalities, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). # Building Blocks From 8b846ee7d81bb7e7a05c9ead50475d7d0041ad9e Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 19 Jun 2023 11:25:38 +0100 Subject: [PATCH 028/157] update lookup table --- tips/TIP-0039/tip-0039.md | 1954 ++++++++++++++++++++++++++++++++++--- 1 file changed, 1832 insertions(+), 122 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 3dc4afbf7..4a15a9e58 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -110,128 +110,1838 @@ Floating point operations might lead to inconsistencies among results in differe We introduce in this section a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^12 * exp(-β * Decay Index Duration * n)`, where `β` and `Decay Index Duration` are protocol parameters, for different values of `n`: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lookup Table: Decays for Mana in slot granularity
nTypedecay(n)
1 (2^0)uint324294966388
2 (2^1)uint324294965480
4 (2^2)uint324294963664
8 (2^3)uint324294960032
16 (2^4)uint324294952769
32 (2^5)uint324294938242
64 (2^6)uint324294909188
128 (2^7)uint324294851080
256 (2^8)uint324294734867
512 (2^9)uint324294502451
1024 (2^10)uint324294037656
2048 (2^11)uint324293108217
4096 (2^12)uint324291249942
8192 (2^13)uint324287535805
16384 (2^14)uint324280117173
32768 (2^15)uint324265318395
65536 (2^16)uint324235874166
131072 (2^17)uint324177594080
262144 (2^18)uint324063428449
524288 (2^19)uint323844371709
1048576 (2^20)uint323441049213
2097152 (2^21)uint322756905669
4194304 (2^22)uint321769636029
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### How to use the lookup table From 0b68e6080a02966726e6a2511e1b08c86c3dfafd Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 19 Jun 2023 11:27:32 +0100 Subject: [PATCH 029/157] move lookup table to the end --- tips/TIP-0039/tip-0039.md | 3672 +++++++++++++++++++------------------ 1 file changed, 1838 insertions(+), 1834 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 4a15a9e58..e7ba6ae25 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -107,1841 +107,9 @@ The decay parameter `β` (together with the Mana generation parameter) were set Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding behavior in different architectures. The results of the operations involving floating point variables might differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, differences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviors in the system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. -We introduce in this section a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^12 * exp(-β * Decay Index Duration * n)`, where `β` and `Decay Index Duration` are protocol parameters, for different values of `n`: +We introduce in the last section of this TIP a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^12 * exp(-β * Decay Index Duration * n)`, where `β` and `Decay Index Duration` are protocol parameters, for different values of `n`. -
Lookup Table: Decays for Mana in decay index granularity scaled to 2^12
nTypedecay(n)
1 + uint16 4092
2 + uint16 4088
3 + uint16 4085
4 + uint16 4081
5 + uint16 4078
6 + uint16 4074
7 + uint16 4071
8 + uint16 4067
9 + uint16 4064
10 + uint16 4060
11 + uint16 4057
12 + uint16 4053
13 + uint16 4050
14 + uint16 4046
15 + uint16 4043
16 + uint16 4039
17 + uint16 4036
18 + uint16 4032
19 + uint16 4029
20 + uint16 4025
21 + uint16 4022
22 + uint16 4018
23 + uint16 4015
24 + uint16 4011
25 + uint16 4008
26 + uint16 4004
27 + uint16 4001
28 + uint16 3997
29 + uint16 3994
30 + uint16 3990
31 + uint16 3987
32 + uint16 3984
33 + uint16 3980
34 + uint16 3977
35 + uint16 3973
36 + uint16 3970
37 + uint16 3966
38 + uint16 3963
39 + uint16 3959
40 + uint16 3956
41 + uint16 3953
42 + uint16 3949
43 + uint16 3946
44 + uint16 3942
45 + uint16 3939
46 + uint16 3936
47 + uint16 3932
48 + uint16 3929
49 + uint16 3925
50 + uint16 3922
51 + uint16 3919
52 + uint16 3915
53 + uint16 3912
54 + uint16 3908
55 + uint16 3905
56 + uint16 3902
57 + uint16 3898
58 + uint16 3895
59 + uint16 3892
60 + uint16 3888
61 + uint16 3885
62 + uint16 3881
63 + uint16 3878
64 + uint16 3875
65 + uint16 3871
66 + uint16 3868
67 + uint16 3865
68 + uint16 3861
69 + uint16 3858
70 + uint16 3855
71 + uint16 3851
72 + uint16 3848
73 + uint16 3845
74 + uint16 3841
75 + uint16 3838
76 + uint16 3835
77 + uint16 3831
78 + uint16 3828
79 + uint16 3825
80 + uint16 3821
81 + uint16 3818
82 + uint16 3815
83 + uint16 3811
84 + uint16 3808
85 + uint16 3805
86 + uint16 3802
87 + uint16 3798
88 + uint16 3795
89 + uint16 3792
90 + uint16 3788
91 + uint16 3785
92 + uint16 3782
93 + uint16 3779
94 + uint16 3775
95 + uint16 3772
96 + uint16 3769
97 + uint16 3766
98 + uint16 3762
99 + uint16 3759
100 + uint16 3756
101 + uint16 3753
102 + uint16 3749
103 + uint16 3746
104 + uint16 3743
105 + uint16 3740
106 + uint16 3736
107 + uint16 3733
108 + uint16 3730
109 + uint16 3727
110 + uint16 3723
111 + uint16 3720
112 + uint16 3717
113 + uint16 3714
114 + uint16 3710
115 + uint16 3707
116 + uint16 3704
117 + uint16 3701
118 + uint16 3698
119 + uint16 3694
120 + uint16 3691
121 + uint16 3688
122 + uint16 3685
123 + uint16 3682
124 + uint16 3678
125 + uint16 3675
126 + uint16 3672
127 + uint16 3669
128 + uint16 3666
129 + uint16 3663
130 + uint16 3659
131 + uint16 3656
132 + uint16 3653
133 + uint16 3650
134 + uint16 3647
135 + uint16 3644
136 + uint16 3640
137 + uint16 3637
138 + uint16 3634
139 + uint16 3631
140 + uint16 3628
141 + uint16 3625
142 + uint16 3622
143 + uint16 3618
144 + uint16 3615
145 + uint16 3612
146 + uint16 3609
147 + uint16 3606
148 + uint16 3603
149 + uint16 3600
150 + uint16 3597
151 + uint16 3593
152 + uint16 3590
153 + uint16 3587
154 + uint16 3584
155 + uint16 3581
156 + uint16 3578
157 + uint16 3575
158 + uint16 3572
159 + uint16 3569
160 + uint16 3566
161 + uint16 3562
162 + uint16 3559
163 + uint16 3556
164 + uint16 3553
165 + uint16 3550
166 + uint16 3547
167 + uint16 3544
168 + uint16 3541
169 + uint16 3538
170 + uint16 3535
171 + uint16 3532
172 + uint16 3529
173 + uint16 3526
174 + uint16 3523
175 + uint16 3520
176 + uint16 3517
177 + uint16 3513
178 + uint16 3510
179 + uint16 3507
180 + uint16 3504
181 + uint16 3501
182 + uint16 3498
183 + uint16 3495
184 + uint16 3492
185 + uint16 3489
186 + uint16 3486
187 + uint16 3483
188 + uint16 3480
189 + uint16 3477
190 + uint16 3474
191 + uint16 3471
192 + uint16 3468
193 + uint16 3465
194 + uint16 3462
195 + uint16 3459
196 + uint16 3456
197 + uint16 3453
198 + uint16 3450
199 + uint16 3447
200 + uint16 3444
201 + uint16 3441
202 + uint16 3438
203 + uint16 3435
204 + uint16 3432
205 + uint16 3429
206 + uint16 3426
207 + uint16 3423
208 + uint16 3420
209 + uint16 3417
210 + uint16 3414
211 + uint16 3412
212 + uint16 3409
213 + uint16 3406
214 + uint16 3403
215 + uint16 3400
216 + uint16 3397
217 + uint16 3394
218 + uint16 3391
219 + uint16 3388
220 + uint16 3385
221 + uint16 3382
222 + uint16 3379
223 + uint16 3376
224 + uint16 3373
225 + uint16 3370
226 + uint16 3368
227 + uint16 3365
228 + uint16 3362
229 + uint16 3359
230 + uint16 3356
231 + uint16 3353
232 + uint16 3350
233 + uint16 3347
234 + uint16 3344
235 + uint16 3341
236 + uint16 3338
237 + uint16 3336
238 + uint16 3333
239 + uint16 3330
240 + uint16 3327
241 + uint16 3324
242 + uint16 3321
243 + uint16 3318
244 + uint16 3315
245 + uint16 3313
246 + uint16 3310
247 + uint16 3307
248 + uint16 3304
249 + uint16 3301
250 + uint16 3298
251 + uint16 3295
252 + uint16 3293
253 + uint16 3290
254 + uint16 3287
255 + uint16 3284
256 + uint16 3281
257 + uint16 3278
258 + uint16 3275
259 + uint16 3273
260 + uint16 3270
261 + uint16 3267
262 + uint16 3264
263 + uint16 3261
264 + uint16 3258
265 + uint16 3256
266 + uint16 3253
267 + uint16 3250
268 + uint16 3247
269 + uint16 3244
270 + uint16 3242
271 + uint16 3239
272 + uint16 3236
273 + uint16 3233
274 + uint16 3230
275 + uint16 3228
276 + uint16 3225
277 + uint16 3222
278 + uint16 3219
279 + uint16 3216
280 + uint16 3214
281 + uint16 3211
282 + uint16 3208
283 + uint16 3205
284 + uint16 3203
285 + uint16 3200
286 + uint16 3197
287 + uint16 3194
288 + uint16 3191
289 + uint16 3189
290 + uint16 3186
291 + uint16 3183
292 + uint16 3180
293 + uint16 3178
294 + uint16 3175
295 + uint16 3172
296 + uint16 3169
297 + uint16 3167
298 + uint16 3164
299 + uint16 3161
300 + uint16 3158
301 + uint16 3156
302 + uint16 3153
303 + uint16 3150
304 + uint16 3148
305 + uint16 3145
306 + uint16 3142
307 + uint16 3139
308 + uint16 3137
309 + uint16 3134
310 + uint16 3131
311 + uint16 3129
312 + uint16 3126
313 + uint16 3123
314 + uint16 3120
315 + uint16 3118
316 + uint16 3115
317 + uint16 3112
318 + uint16 3110
319 + uint16 3107
320 + uint16 3104
321 + uint16 3102
322 + uint16 3099
323 + uint16 3096
324 + uint16 3093
325 + uint16 3091
326 + uint16 3088
327 + uint16 3085
328 + uint16 3083
329 + uint16 3080
330 + uint16 3077
331 + uint16 3075
332 + uint16 3072
333 + uint16 3069
334 + uint16 3067
335 + uint16 3064
336 + uint16 3062
337 + uint16 3059
338 + uint16 3056
339 + uint16 3054
340 + uint16 3051
341 + uint16 3048
342 + uint16 3046
343 + uint16 3043
344 + uint16 3040
345 + uint16 3038
346 + uint16 3035
347 + uint16 3032
348 + uint16 3030
349 + uint16 3027
350 + uint16 3025
351 + uint16 3022
352 + uint16 3019
353 + uint16 3017
354 + uint16 3014
355 + uint16 3012
356 + uint16 3009
357 + uint16 3006
358 + uint16 3004
359 + uint16 3001
360 + uint16 2999
361 + uint16 2996
362 + uint16 2993
363 + uint16 2991
364 + uint16 2988
365 + uint16 2986
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### How to use the lookup table @@ -2279,7 +447,1843 @@ Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA ## Transaction Payload -[TIP-20](../TIP-0020/tip-0020.md) is the basis for output validation in this TIP. +[TIP-20](../TIP-0020/tip-0020.md) is the basis for output validation in this TIP. + +## Lookup Table + + +
Lookup Table: Decays for Mana in decay index granularity scaled to 2^12
nTypedecay(n)
1 - uint16 4092
2 - uint16 4088
3 - uint16 4085
4 - uint16 4081
5 - uint16 4078
6 - uint16 4074
7 - uint16 4071
8 - uint16 4067
9 - uint16 4064
10 - uint16 4060
11 - uint16 4057
12 - uint16 4053
13 - uint16 4050
14 - uint16 4046
15 - uint16 4043
16 - uint16 4039
17 - uint16 4036
18 - uint16 4032
19 - uint16 4029
20 - uint16 4025
21 - uint16 4022
22 - uint16 4018
23 - uint16 4015
24 - uint16 4011
25 - uint16 4008
26 - uint16 4004
27 - uint16 4001
28 - uint16 3997
29 - uint16 3994
30 - uint16 3990
31 - uint16 3987
32 - uint16 3984
33 - uint16 3980
34 - uint16 3977
35 - uint16 3973
36 - uint16 3970
37 - uint16 3966
38 - uint16 3963
39 - uint16 3959
40 - uint16 3956
41 - uint16 3953
42 - uint16 3949
43 - uint16 3946
44 - uint16 3942
45 - uint16 3939
46 - uint16 3936
47 - uint16 3932
48 - uint16 3929
49 - uint16 3925
50 - uint16 3922
51 - uint16 3919
52 - uint16 3915
53 - uint16 3912
54 - uint16 3908
55 - uint16 3905
56 - uint16 3902
57 - uint16 3898
58 - uint16 3895
59 - uint16 3892
60 - uint16 3888
61 - uint16 3885
62 - uint16 3881
63 - uint16 3878
64 - uint16 3875
65 - uint16 3871
66 - uint16 3868
67 - uint16 3865
68 - uint16 3861
69 - uint16 3858
70 - uint16 3855
71 - uint16 3851
72 - uint16 3848
73 - uint16 3845
74 - uint16 3841
75 - uint16 3838
76 - uint16 3835
77 - uint16 3831
78 - uint16 3828
79 - uint16 3825
80 - uint16 3821
81 - uint16 3818
82 - uint16 3815
83 - uint16 3811
84 - uint16 3808
85 - uint16 3805
86 - uint16 3802
87 - uint16 3798
88 - uint16 3795
89 - uint16 3792
90 - uint16 3788
91 - uint16 3785
92 - uint16 3782
93 - uint16 3779
94 - uint16 3775
95 - uint16 3772
96 - uint16 3769
97 - uint16 3766
98 - uint16 3762
99 - uint16 3759
100 - uint16 3756
101 - uint16 3753
102 - uint16 3749
103 - uint16 3746
104 - uint16 3743
105 - uint16 3740
106 - uint16 3736
107 - uint16 3733
108 - uint16 3730
109 - uint16 3727
110 - uint16 3723
111 - uint16 3720
112 - uint16 3717
113 - uint16 3714
114 - uint16 3710
115 - uint16 3707
116 - uint16 3704
117 - uint16 3701
118 - uint16 3698
119 - uint16 3694
120 - uint16 3691
121 - uint16 3688
122 - uint16 3685
123 - uint16 3682
124 - uint16 3678
125 - uint16 3675
126 - uint16 3672
127 - uint16 3669
128 - uint16 3666
129 - uint16 3663
130 - uint16 3659
131 - uint16 3656
132 - uint16 3653
133 - uint16 3650
134 - uint16 3647
135 - uint16 3644
136 - uint16 3640
137 - uint16 3637
138 - uint16 3634
139 - uint16 3631
140 - uint16 3628
141 - uint16 3625
142 - uint16 3622
143 - uint16 3618
144 - uint16 3615
145 - uint16 3612
146 - uint16 3609
147 - uint16 3606
148 - uint16 3603
149 - uint16 3600
150 - uint16 3597
151 - uint16 3593
152 - uint16 3590
153 - uint16 3587
154 - uint16 3584
155 - uint16 3581
156 - uint16 3578
157 - uint16 3575
158 - uint16 3572
159 - uint16 3569
160 - uint16 3566
161 - uint16 3562
162 - uint16 3559
163 - uint16 3556
164 - uint16 3553
165 - uint16 3550
166 - uint16 3547
167 - uint16 3544
168 - uint16 3541
169 - uint16 3538
170 - uint16 3535
171 - uint16 3532
172 - uint16 3529
173 - uint16 3526
174 - uint16 3523
175 - uint16 3520
176 - uint16 3517
177 - uint16 3513
178 - uint16 3510
179 - uint16 3507
180 - uint16 3504
181 - uint16 3501
182 - uint16 3498
183 - uint16 3495
184 - uint16 3492
185 - uint16 3489
186 - uint16 3486
187 - uint16 3483
188 - uint16 3480
189 - uint16 3477
190 - uint16 3474
191 - uint16 3471
192 - uint16 3468
193 - uint16 3465
194 - uint16 3462
195 - uint16 3459
196 - uint16 3456
197 - uint16 3453
198 - uint16 3450
199 - uint16 3447
200 - uint16 3444
201 - uint16 3441
202 - uint16 3438
203 - uint16 3435
204 - uint16 3432
205 - uint16 3429
206 - uint16 3426
207 - uint16 3423
208 - uint16 3420
209 - uint16 3417
210 - uint16 3414
211 - uint16 3412
212 - uint16 3409
213 - uint16 3406
214 - uint16 3403
215 - uint16 3400
216 - uint16 3397
217 - uint16 3394
218 - uint16 3391
219 - uint16 3388
220 - uint16 3385
221 - uint16 3382
222 - uint16 3379
223 - uint16 3376
224 - uint16 3373
225 - uint16 3370
226 - uint16 3368
227 - uint16 3365
228 - uint16 3362
229 - uint16 3359
230 - uint16 3356
231 - uint16 3353
232 - uint16 3350
233 - uint16 3347
234 - uint16 3344
235 - uint16 3341
236 - uint16 3338
237 - uint16 3336
238 - uint16 3333
239 - uint16 3330
240 - uint16 3327
241 - uint16 3324
242 - uint16 3321
243 - uint16 3318
244 - uint16 3315
245 - uint16 3313
246 - uint16 3310
247 - uint16 3307
248 - uint16 3304
249 - uint16 3301
250 - uint16 3298
251 - uint16 3295
252 - uint16 3293
253 - uint16 3290
254 - uint16 3287
255 - uint16 3284
256 - uint16 3281
257 - uint16 3278
258 - uint16 3275
259 - uint16 3273
260 - uint16 3270
261 - uint16 3267
262 - uint16 3264
263 - uint16 3261
264 - uint16 3258
265 - uint16 3256
266 - uint16 3253
267 - uint16 3250
268 - uint16 3247
269 - uint16 3244
270 - uint16 3242
271 - uint16 3239
272 - uint16 3236
273 - uint16 3233
274 - uint16 3230
275 - uint16 3228
276 - uint16 3225
277 - uint16 3222
278 - uint16 3219
279 - uint16 3216
280 - uint16 3214
281 - uint16 3211
282 - uint16 3208
283 - uint16 3205
284 - uint16 3203
285 - uint16 3200
286 - uint16 3197
287 - uint16 3194
288 - uint16 3191
289 - uint16 3189
290 - uint16 3186
291 - uint16 3183
292 - uint16 3180
293 - uint16 3178
294 - uint16 3175
295 - uint16 3172
296 - uint16 3169
297 - uint16 3167
298 - uint16 3164
299 - uint16 3161
300 - uint16 3158
301 - uint16 3156
302 - uint16 3153
303 - uint16 3150
304 - uint16 3148
305 - uint16 3145
306 - uint16 3142
307 - uint16 3139
308 - uint16 3137
309 - uint16 3134
310 - uint16 3131
311 - uint16 3129
312 - uint16 3126
313 - uint16 3123
314 - uint16 3120
315 - uint16 3118
316 - uint16 3115
317 - uint16 3112
318 - uint16 3110
319 - uint16 3107
320 - uint16 3104
321 - uint16 3102
322 - uint16 3099
323 - uint16 3096
324 - uint16 3093
325 - uint16 3091
326 - uint16 3088
327 - uint16 3085
328 - uint16 3083
329 - uint16 3080
330 - uint16 3077
331 - uint16 3075
332 - uint16 3072
333 - uint16 3069
334 - uint16 3067
335 - uint16 3064
336 - uint16 3062
337 - uint16 3059
338 - uint16 3056
339 - uint16 3054
340 - uint16 3051
341 - uint16 3048
342 - uint16 3046
343 - uint16 3043
344 - uint16 3040
345 - uint16 3038
346 - uint16 3035
347 - uint16 3032
348 - uint16 3030
349 - uint16 3027
350 - uint16 3025
351 - uint16 3022
352 - uint16 3019
353 - uint16 3017
354 - uint16 3014
355 - uint16 3012
356 - uint16 3009
357 - uint16 3006
358 - uint16 3004
359 - uint16 3001
360 - uint16 2999
361 - uint16 2996
362 - uint16 2993
363 - uint16 2991
364 - uint16 2988
365 - uint16 2986
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Copyright From e21a7bb1df38fa5a9273f3abda4b5ddde2e30e15 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 19 Jun 2023 11:28:53 +0100 Subject: [PATCH 030/157] minor change --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index e7ba6ae25..aed8087c9 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -146,7 +146,7 @@ based on the UTXO IOTA token value and the time it was created stored in the UTX We model the potential Mana generated by an output holding `amount` IOTA tokens as the combination of a fixed generation per slot `generation_per_slot * amount` and a decay equivalent to a multiplication by `2^(-12)*decay(1)` everytime a decay index ends. ![](https://hackmd.io/_uploads/Bkzz3PiD2.png) - +FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW Let `i` be the decay index of the creation slot and `j` be the decay index of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in decay index `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in decay index `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n- 1` times, and so on, until the Mana generated in decay index `j`, which is not decayed at all. Adding these values, we find the following formulas: From ed4a44f5b399ca74c867531733d09d480b8248ab Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 19 Jun 2023 11:47:11 +0100 Subject: [PATCH 031/157] change mana generation --- tips/TIP-0039/tip-0039.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index aed8087c9..9926abc83 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -163,7 +163,7 @@ Let `i` be the decay index of the creation slot and `j` be the decay index of th - `slot_after_decay_index_i` is the first slot of the decay index `i + 1` ; - `d2 = consumption_slot - first_slot_decay_index_j` - `first_slot_decay_index_j` is the first slot of decay index `j` ; - - `generation_per_slot = 2^(-3)` is the Mana generated by holding 1 IOTA for 1 slot. + - `generation_per_slot = 2^(-27)` is the Mana generated by holding 1 IOTA for 1 slot. The exact order of the operations that must be done are defined in the next section. @@ -188,7 +188,7 @@ if creation_decay_index == consumption_decay_index: } potential_mana = amount * (consumption_slot - creation_slot) - potential_mana = potential_mana >> 3 - bitsDecreased + potential_mana = potential_mana >> 27 - bitsDecreased elif creation_decay_index + 1 == consumption_decay_index: @@ -201,12 +201,12 @@ elif creation_decay_index + 1 == consumption_decay_index: bitsDecreased++ } - potential_mana = amount * (d1*1023 + d2*1024) *2^(-(13- bitsDecreased)) + potential_mana = amount * (d1*1023 + d2*1024) *2^(-(37- bitsDecreased)) else: d1 = slot_after_creation_decay_index - creation_slot d2 = consumption_slot - first_slot_consumption_decay_index - potential_mana = amount *2^(-3) * 2^(-12)(d1*decay(n) + 4096 d2 +8380416*(4096-decay(n-1))) + potential_mana = amount *2^(-27) * 2^(-12)(d1*decay(n) + 4096 d2 +8380416*(4096-decay(n-1))) ``` From c9449654278525b93b3be7bf6d3198367c200aad Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 19 Jun 2023 12:56:22 +0100 Subject: [PATCH 032/157] minor changes --- tips/TIP-0039/tip-0039.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 9926abc83..09d83d995 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -65,8 +65,8 @@ Additionally, Mana implementation is strictly connected to the accounts introduc * [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved within certain rules between the different owners, which allows for Mana market development. * [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. -* When the user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit form, -mentioned before stored Mana, and store the resource directly in the UTXO ledger, or the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). +* When the user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit form +(the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If a user does not store the potential Mana when consuming the output, she will forfeit this Mana. Alternatively, the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). * [**Mana rewards**](#mana-rewards) is another form of Mana used to reward for participation in staking for validation and delegating IOTA tokens. The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. From 913702c43baa8c268a6212c239cdc031bbab1345 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 19 Jun 2023 13:08:10 +0100 Subject: [PATCH 033/157] minor changes --- tips/TIP-0039/tip-0039.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 09d83d995..7dd8f3460 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -67,7 +67,7 @@ Additionally, Mana implementation is strictly connected to the accounts introduc It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. * When the user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit form (the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If a user does not store the potential Mana when consuming the output, she will forfeit this Mana. Alternatively, the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). -* [**Mana rewards**](#mana-rewards) is another form of Mana used to reward for participation in staking for validation and delegating IOTA tokens. +* [**Mana rewards**](#mana-rewards) are used to reward for participation in staking for validation and delegating IOTA tokens. The Mana rewarded from staking and validation must be claimed and stored as stored Mana. The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. @@ -75,9 +75,8 @@ The **Mana holdings** are referred to as the sum of all the potential Mana and s According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a certain amount of Mana dictated by the size of the block and the Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Therefore, in order to prevent being locked out of their account, the block issuer must ensure that sufficient Mana is also allotted to their account to ensure their BIC balance remains non-negative. ### Reference Mana Cost -*Reference Mana Cost (RMC)* is used to decide upon commitment how much Mana is burned from BIC by each block in that slot. -RMC is computed according to an algorithm based on recent traffic activity: the algorithm counts the number of blocks in slots that are *Maximum Committable Age (MCA)* slots in the past -so that all nodes agree on that value of RMC. +*Reference Mana Cost (RMC)* is used to decide how much Mana should be burned from BIC by each block in that slot. +RMC is computed according to an algorithm based on recent traffic activity: the algorithm counts the number of blocks in slots that are *Maximum Committable Age (MCA)* slots in the past so that all nodes agree on that value of RMC and know this value in advance (before issuing the block). From a high-level perspective, the RMC algorithm works as follows: - If the number of blocks in slot `i - MCA` is larger than a given threshold, then the RMC increases. @@ -89,8 +88,7 @@ Note that blocks from issuers with negative BIC balances are excluded with respe To limit fluctuations in the RMC, it is proposed to update its value every MCA slot at least. ## Mana decay -Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. To guarantee non-gameability (any certain behavior, e.g., -splitting accounts, cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs to be applied to all forms of Mana: +Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. To guarantee non-gameability (e.g., splitting accounts or other behaviours that are not helpful for the system well-functioning cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs to be applied to all forms of Mana: - newly generated Mana ([Potential Mana](#potential-mana)); - Mana stored in UTXOs ([Stored Mana](#stored-mana)); @@ -101,7 +99,7 @@ As the form in which the decay factor will be applied might differ between the M Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on decay indices, not local times. Every`8192` slots, the decay index changes, meaning that every set of consecutive `2^(13)` slots will have the same decay index. -The decay parameter `β` (together with the Mana generation parameter) were set so the maximum theoretical Mana in the system is `2^53-1`. This means that, even though Mana is stored as a int64, it effectively uses 54 bits (53 for the value and one for the sign). Notice that this value of `2^53-1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^53-1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. +The decay parameter `β` (together with the Mana generation parameter) were set so the maximum theoretical Mana in the system is `2^53-1`. This means that, even though Mana is stored as a uint64, it effectively uses 53 bits (in the case of BIC, it uses 54 bits, 53 for the value and one for the sign). Notice that this value of `2^53-1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^53-1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. ## Mana and fixed point arithmetics @@ -109,8 +107,6 @@ Floating point operations might lead to inconsistencies among results in differe We introduce in the last section of this TIP a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^12 * exp(-β * Decay Index Duration * n)`, where `β` and `Decay Index Duration` are protocol parameters, for different values of `n`. - - ### How to use the lookup table ==TO DO: decide to max decay index in the table== From c4caf87992f0cf892a824b0c1cd586588e9b7fd2 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 19 Jun 2023 13:09:42 +0100 Subject: [PATCH 034/157] minor changes --- tips/TIP-0039/tip-0039.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 7dd8f3460..8c59eb21e 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -111,7 +111,7 @@ We introduce in the last section of this TIP a lookup table that will be used in ==TO DO: decide to max decay index in the table== -The table defined above only gives the values of `decay(n)` for some values of `n` up to 365. To calculate `decay(n)` for larger values of `n`, we combine values of given `n` using the following algorithm: +The table defined above only gives the values of `decay(n)` for some values of `n` up to 365. To calculate `decay(n)` for larger values of `n`, we combine values of decays for other numbers smaller than 365, using the following algorithm: - If `n > 365`: Let `n/365` be an integer division (e.g., `367/365 = 1`) and `n mod 365` be the module operation (e.g., `367 mod 365 = 2`). @@ -135,7 +135,7 @@ Example: suppose one needs to calculate `1002*99/100*21/100`. Following the left *Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not, generates potential Mana. The view on the potential Mana value can be deterministically derived from the UTXO ledger, -based on the UTXO IOTA token value and the time it was created stored in the UTXO metadata (the creation time is the slot index of the transaction). +based on the UTXO IOTA token value and the time it was created in the UTXO metadata (we consider the creation time as the slot index of the transaction). ### Rationale behind the Potential Mana formulas From 68a8817ad94f70e1ea1625293dd3a0e32d31b63f Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Thu, 22 Jun 2023 15:50:48 +0100 Subject: [PATCH 035/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 84 +++++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 8c59eb21e..2130288d4 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -97,7 +97,7 @@ Mana decay is introduced as a control mechanism of the Mana dynamics, altogether As the form in which the decay factor will be applied might differ between the Mana types, it is essential to point out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. -Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on decay indices, not local times. Every`8192` slots, the decay index changes, meaning that every set of consecutive `2^(13)` slots will have the same decay index. +Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every`8192` slots, the epoch changes, meaning that every set of consecutive `2^(13)` slots will be in the same epoch. The decay parameter `β` (together with the Mana generation parameter) were set so the maximum theoretical Mana in the system is `2^53-1`. This means that, even though Mana is stored as a uint64, it effectively uses 53 bits (in the case of BIC, it uses 54 bits, 53 for the value and one for the sign). Notice that this value of `2^53-1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^53-1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. @@ -139,32 +139,84 @@ based on the UTXO IOTA token value and the time it was created in the UTXO metad ### Rationale behind the Potential Mana formulas -We model the potential Mana generated by an output holding `amount` IOTA tokens as the combination of a fixed generation per slot `generation_per_slot * amount` and a decay equivalent to a multiplication by `2^(-12)*decay(1)` everytime a decay index ends. +We model the potential Mana generated by an output holding $S$ IOTA tokens as the combination of a fixed generation per slot $\gamma S$ and a decay equivalent to a multiplication by $\exp(-\beta \Delta)$ everytime a decay index ends, where $\Delta$ is the decay index duration. ![](https://hackmd.io/_uploads/Bkzz3PiD2.png) -FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW - -Let `i` be the decay index of the creation slot and `j` be the decay index of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in decay index `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in decay index `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n- 1` times, and so on, until the Mana generated in decay index `j`, which is not decayed at all. Adding these values, we find the following formulas: -- If `n > 1`: - `Potential_Mana = amount * generation_per_slot (d1*decay(n)*2^(-12) + d2 + slots_per_decay_index * decay(1)*(1-decay(n-1)*2^(-12))/(2^(12)-decay(1)))` -- If `n = 1`: - `Potential_Mana = amount * generation_per_slot (d1*decay(1)*2^(-12) + d2)` -- If `n = 0`: - `Potential_Mana = amount * generation_per_slot * (d1+d2)` +FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW - where - - `slots_per_decay_index` is the number of slot in an epoch , i.e., `8192` +Let $i$ be the decay index of the creation slot and $j$ be the decay index of the consumption slot. Let $n=j-i$ and for the sake of the explanation, assume $n>1$. All the Mana generated in decay index $i$ "crosses" $n$ decay boundaries, thus, it must be decayed $n$ times. The Mana generated in decay index $i+1$ "crosses" $n-1$ decay boundaries, so it must be decayed $n-1$ times, and so on, until the Mana generated in decay index $j$, which is not decayed at all. Adding these values, we find the following formulas (here $d$ is the number of slots in a decay index): + +$$ +\begin{align} +\text{Potential Mana} =& \gamma S d_1 \exp(-\beta \Delta n)+\gamma S d \exp(-\beta \Delta (n-1))\\ +&+\gamma S d \exp(-\beta \Delta (n-2)) + \dots +\gamma S d \exp(-\beta \Delta ) + \gamma S d_2 \\ +=& \gamma S d_1 \exp(-\beta \Delta n)+ \gamma S d_2+\Sigma_{i=1}^{n-1}\gamma S d \exp(-\beta \Delta i)\\ +=& \gamma S \left[d_1 \exp(-\beta \Delta n)+ d_2+ d\exp(-\beta \Delta)\frac{1-\exp(-\beta \Delta (n-1))}{1-\exp(-\beta \Delta)}\right] +\end{align} +$$ + +Analogously, if $n\leq 1$, we find the following results (here $\delta$ is the difference between the creation and consumption slots): +$$ +\text{Potential Mana} = \begin{cases} +\gamma S d_1 \exp(-\beta \Delta ) + \gamma S d_2, \text{ if }n=1 \\ +\gamma S \delta , \text{ if }n=0 \\ +\end{cases} +$$ + +### Potential Mana formulas with fixed point arithmetics + +The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for $n>1$, noticing that we already approximated $2^{\text{k}}\exp(-\beta \Delta i)$ by `decay(i)`, where $k$ is the precision of the Lookup table used: + +- If `n > 1`: Let `c` be an integer approximation of $\frac{\exp(-\beta \Delta)}{1-\exp(-\beta \Delta)}$. Then, `Potential_Mana = Potential_Mana_0 + Potential_Mana_n + Potential_Mana_n_1`, where: + - `Potential_Mana_0 = amount * generation_per_slot * d2 + c * amount * generation_per_slot * slots_per_decay_index` + - `Potential_Mana_n = amount * generation_per_slot * d1 * decay(n) * 2^(-k) ` + - `Potential_Mana_n_1 = - c * amount * generation_per_slot * slots_per_decay_index * decay(n-1) * 2^(-k)` + + and + - `slots_per_decay_index` is the number of slots in a decay index - `d1 = slot_after_decay_index_i - creation_slot` - `slot_after_decay_index_i` is the first slot of the decay index `i + 1` ; - `d2 = consumption_slot - first_slot_decay_index_j` - `first_slot_decay_index_j` is the first slot of decay index `j` ; - - `generation_per_slot = 2^(-27)` is the Mana generated by holding 1 IOTA for 1 slot. - - + - `generation_per_slot` is the Mana generated by holding 1 IOTA for 1 slot. + +We begin by applying to the formulas above some of the protocol parameters. Specifically, we use that +- $\beta = 1/3$ per year +- `slots_per_decay_index = 2^13` +- Duration of a slot is 10 seconds. This means that the duration of a decay index in years is around $\Delta = 0.002597666159$. + +With the values above, we approximate `c = 1154`. Also, we use `generation_per_slot = 2^(-27)`. Notice that if any of those values are changed in the future, the formulas below in this TIP might become deprecated. Applying the simmplifications mentioned above, we have: +- `Potential_Mana_0 = amount * d2 * 2^(-27) + 1154 * amount * 2^(-14)` +- `Potential_Mana_n = amount * d1 * decay(n) * 2^(-k-27) ` +- `Potential_Mana_n_1 = - 1154 * amount * decay(n-1) * 2^(-k-14)` + +Analogously, we find formulas for `n<2:` +- If `n = 1`: `Potential_Mana = amount * d1 * decay(1) * 2^(-k-27) + amount * d2 * 2^(-27)` +- If `n = 0`: `Potential_Mana = amount * (consumption_slot-creation_slot) * 2^(-27)` + + + +# MAX, IT'S GOOD UNTIL THIS POINT + + The exact order of the operations that must be done are defined in the next section. + + + + + + + + + + + + + + ### Potential Mana Semantic Validation - Potential Mana must and can only be consumed when the corresponding output is consumed. - When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the accumulated potential Mana value. There are three options: From 615752aaf19e0ffc090a87a391ae30558eee798c Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Mon, 10 Jul 2023 17:53:29 +0200 Subject: [PATCH 036/157] Start changing Latex formulas --- tips/TIP-0039/tip-0039.md | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 2130288d4..84d368088 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -99,7 +99,7 @@ As the form in which the decay factor will be applied might differ between the M Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every`8192` slots, the epoch changes, meaning that every set of consecutive `2^(13)` slots will be in the same epoch. -The decay parameter `β` (together with the Mana generation parameter) were set so the maximum theoretical Mana in the system is `2^53-1`. This means that, even though Mana is stored as a uint64, it effectively uses 53 bits (in the case of BIC, it uses 54 bits, 53 for the value and one for the sign). Notice that this value of `2^53-1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^53-1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. +The decay parameter `β` (together with the Mana generation parameter) were set so the maximum theoretical Mana in the system is `2^53 - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses 53 bits (in the case of BIC, it uses 54 bits, 53 for the value and one for the sign). Notice that this value of `2^53 - 1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^53 - 1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. ## Mana and fixed point arithmetics @@ -139,36 +139,29 @@ based on the UTXO IOTA token value and the time it was created in the UTXO metad ### Rationale behind the Potential Mana formulas -We model the potential Mana generated by an output holding $S$ IOTA tokens as the combination of a fixed generation per slot $\gamma S$ and a decay equivalent to a multiplication by $\exp(-\beta \Delta)$ everytime a decay index ends, where $\Delta$ is the decay index duration. +We model the potential Mana generated by an output holding `S` IOTA tokens as the combination of a fixed generation per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time a decay index ends, where `Δ` is the decay index duration. ![](https://hackmd.io/_uploads/Bkzz3PiD2.png) FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW -Let $i$ be the decay index of the creation slot and $j$ be the decay index of the consumption slot. Let $n=j-i$ and for the sake of the explanation, assume $n>1$. All the Mana generated in decay index $i$ "crosses" $n$ decay boundaries, thus, it must be decayed $n$ times. The Mana generated in decay index $i+1$ "crosses" $n-1$ decay boundaries, so it must be decayed $n-1$ times, and so on, until the Mana generated in decay index $j$, which is not decayed at all. Adding these values, we find the following formulas (here $d$ is the number of slots in a decay index): - -$$ -\begin{align} -\text{Potential Mana} =& \gamma S d_1 \exp(-\beta \Delta n)+\gamma S d \exp(-\beta \Delta (n-1))\\ -&+\gamma S d \exp(-\beta \Delta (n-2)) + \dots +\gamma S d \exp(-\beta \Delta ) + \gamma S d_2 \\ -=& \gamma S d_1 \exp(-\beta \Delta n)+ \gamma S d_2+\Sigma_{i=1}^{n-1}\gamma S d \exp(-\beta \Delta i)\\ -=& \gamma S \left[d_1 \exp(-\beta \Delta n)+ d_2+ d\exp(-\beta \Delta)\frac{1-\exp(-\beta \Delta (n-1))}{1-\exp(-\beta \Delta)}\right] -\end{align} -$$ - -Analogously, if $n\leq 1$, we find the following results (here $\delta$ is the difference between the creation and consumption slots): -$$ -\text{Potential Mana} = \begin{cases} -\gamma S d_1 \exp(-\beta \Delta ) + \gamma S d_2, \text{ if }n=1 \\ -\gamma S \delta , \text{ if }n=0 \\ -\end{cases} -$$ +Let `i` be the decay index of the creation slot and `j` be the decay index of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in decay index `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in decay index `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n - 1` times, and so on, until the Mana generated in decay index `j`, which is not decayed at all. Adding these values, we find the following formulas (here `d` is the number of slots in a decay index): + +Potential Mana = γ * S * d1 * exp(-β * Δ * n) + γ * S * d * exp(-β * Δ * (n - 1)) ++ γ * S * d * exp(-β * Δ * (n - 2)) + ... + γ * S * d * exp(-β * Δ) + γ * S * d2 += γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) += γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))], i = 1, ..., n - 1. + + +Analogously, if `n ≤ 1`, we find the following results (here `δ` is the difference between the creation and consumption slots): +Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2, if `n = 1` +`γ * S * δ`, if `n = 0`. ### Potential Mana formulas with fixed point arithmetics -The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for $n>1$, noticing that we already approximated $2^{\text{k}}\exp(-\beta \Delta i)$ by `decay(i)`, where $k$ is the precision of the Lookup table used: +The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated 2k * exp(-β * Δ * i) by `decay(i)`, where `k` is the precision of the Lookup table used: -- If `n > 1`: Let `c` be an integer approximation of $\frac{\exp(-\beta \Delta)}{1-\exp(-\beta \Delta)}$. Then, `Potential_Mana = Potential_Mana_0 + Potential_Mana_n + Potential_Mana_n_1`, where: +- If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))`. Then, `Potential_Mana = Potential_Mana_0 + Potential_Mana_n + Potential_Mana_n_1`, where: - `Potential_Mana_0 = amount * generation_per_slot * d2 + c * amount * generation_per_slot * slots_per_decay_index` - `Potential_Mana_n = amount * generation_per_slot * d1 * decay(n) * 2^(-k) ` - `Potential_Mana_n_1 = - c * amount * generation_per_slot * slots_per_decay_index * decay(n-1) * 2^(-k)` From 983651bbc23a5e74a258a8389875b698f4b6088d Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Mon, 10 Jul 2023 18:01:13 +0200 Subject: [PATCH 037/157] Remove subscripts --- tips/TIP-0039/tip-0039.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 84d368088..e69d1813b 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -147,19 +147,18 @@ FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW Let `i` be the decay index of the creation slot and `j` be the decay index of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in decay index `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in decay index `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n - 1` times, and so on, until the Mana generated in decay index `j`, which is not decayed at all. Adding these values, we find the following formulas (here `d` is the number of slots in a decay index): -Potential Mana = γ * S * d1 * exp(-β * Δ * n) + γ * S * d * exp(-β * Δ * (n - 1)) -+ γ * S * d * exp(-β * Δ * (n - 2)) + ... + γ * S * d * exp(-β * Δ) + γ * S * d2 -= γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) -= γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))], i = 1, ..., n - 1. - +`Potential Mana = γ * S * d1 * exp(-β * Δ * n) + γ * S * d * exp(-β * Δ * (n - 1)) + ` +`+ γ * S * d * exp(-β * Δ * (n - 2)) + ... + γ * S * d * exp(-β * Δ) + γ * S * d2 = ` +`= γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = ` +`= γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))], i = 1, ..., n - 1`. Analogously, if `n ≤ 1`, we find the following results (here `δ` is the difference between the creation and consumption slots): -Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2, if `n = 1` -`γ * S * δ`, if `n = 0`. +- Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2, if `n = 1` +- `γ * S * δ`, if `n = 0`. ### Potential Mana formulas with fixed point arithmetics -The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated 2k * exp(-β * Δ * i) by `decay(i)`, where `k` is the precision of the Lookup table used: +The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated `2^k * exp(-β * Δ * i)` by `decay(i)`, where `k` is the precision of the Lookup table used: - If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))`. Then, `Potential_Mana = Potential_Mana_0 + Potential_Mana_n + Potential_Mana_n_1`, where: - `Potential_Mana_0 = amount * generation_per_slot * d2 + c * amount * generation_per_slot * slots_per_decay_index` From 07f6c6e136a123871a730f54698c6eec10b86c90 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 11 Jul 2023 12:38:10 +0200 Subject: [PATCH 038/157] Fix long potential Mana formula --- tips/TIP-0039/tip-0039.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index e69d1813b..4f33cb010 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -147,14 +147,14 @@ FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW Let `i` be the decay index of the creation slot and `j` be the decay index of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in decay index `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in decay index `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n - 1` times, and so on, until the Mana generated in decay index `j`, which is not decayed at all. Adding these values, we find the following formulas (here `d` is the number of slots in a decay index): -`Potential Mana = γ * S * d1 * exp(-β * Δ * n) + γ * S * d * exp(-β * Δ * (n - 1)) + ` -`+ γ * S * d * exp(-β * Δ * (n - 2)) + ... + γ * S * d * exp(-β * Δ) + γ * S * d2 = ` +`Potential Mana = γ * S * [d1 * exp(-β * Δ * n) + d * exp(-β * Δ * (n - 1)) + d * exp(-β * Δ * (n - 2)) + ... + d * exp(-β * Δ) + d2] = ` + `= γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = ` `= γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))], i = 1, ..., n - 1`. Analogously, if `n ≤ 1`, we find the following results (here `δ` is the difference between the creation and consumption slots): -- Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2, if `n = 1` -- `γ * S * δ`, if `n = 0`. +- If `n = 1`: `Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2`. +- If `n = 0`: `Potential Mana = γ * S * δ`. ### Potential Mana formulas with fixed point arithmetics From 52eef8d4391d2529e5629c557cd773b1f45b2774 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 11 Jul 2023 12:43:05 +0200 Subject: [PATCH 039/157] Fixing long potential Mana formula --- tips/TIP-0039/tip-0039.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 4f33cb010..9252252dc 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -147,10 +147,10 @@ FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW Let `i` be the decay index of the creation slot and `j` be the decay index of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in decay index `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in decay index `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n - 1` times, and so on, until the Mana generated in decay index `j`, which is not decayed at all. Adding these values, we find the following formulas (here `d` is the number of slots in a decay index): -`Potential Mana = γ * S * [d1 * exp(-β * Δ * n) + d * exp(-β * Δ * (n - 1)) + d * exp(-β * Δ * (n - 2)) + ... + d * exp(-β * Δ) + d2] = ` +`Potential Mana = γ*S*[d1*exp(-β * Δ * n) + d*exp(-β * Δ * (n - 1)) + d*exp(-β * Δ * (n - 2)) + ... + d*exp(-β * Δ) + d2] =` -`= γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = ` -`= γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))], i = 1, ..., n - 1`. += γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = += γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))], i = 1, ..., n - 1. Analogously, if `n ≤ 1`, we find the following results (here `δ` is the difference between the creation and consumption slots): - If `n = 1`: `Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2`. From 54f24d715b8fe07da2e22e300287a0f3af849d92 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 11 Jul 2023 12:46:30 +0200 Subject: [PATCH 040/157] Fixing long potential Mana formula --- tips/TIP-0039/tip-0039.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 9252252dc..3cb5eb18f 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -147,10 +147,9 @@ FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW Let `i` be the decay index of the creation slot and `j` be the decay index of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in decay index `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in decay index `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n - 1` times, and so on, until the Mana generated in decay index `j`, which is not decayed at all. Adding these values, we find the following formulas (here `d` is the number of slots in a decay index): -`Potential Mana = γ*S*[d1*exp(-β * Δ * n) + d*exp(-β * Δ * (n - 1)) + d*exp(-β * Δ * (n - 2)) + ... + d*exp(-β * Δ) + d2] =` - -= γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = -= γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))], i = 1, ..., n - 1. +`Potential Mana = γ * S * [d1 * exp(-β * Δ * n) + d * exp(-β * Δ * (n - 1)) + d * exp(-β * Δ * (n - 2)) + ... + d * exp(-β * Δ) + d2] = +γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = +γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))]`, where the summation is over `i = 1, ..., n - 1`. Analogously, if `n ≤ 1`, we find the following results (here `δ` is the difference between the creation and consumption slots): - If `n = 1`: `Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2`. From 530a555a2cdf54c654bcbff23fe57a13d4f4f1ce Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 11 Jul 2023 12:55:19 +0200 Subject: [PATCH 041/157] Get rid of Latex --- tips/TIP-0039/tip-0039.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 3cb5eb18f..7227346a1 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -173,18 +173,18 @@ The formulas found in the last section are the exact formulas for the model prop - `generation_per_slot` is the Mana generated by holding 1 IOTA for 1 slot. We begin by applying to the formulas above some of the protocol parameters. Specifically, we use that -- $\beta = 1/3$ per year -- `slots_per_decay_index = 2^13` -- Duration of a slot is 10 seconds. This means that the duration of a decay index in years is around $\Delta = 0.002597666159$. +- `β= 1/3` per year; +- `slots_per_decay_index = 2^13`; +- Duration of a slot is 10 seconds. This means that the duration of a decay index in years is around `Δ = 0.002597666159`. With the values above, we approximate `c = 1154`. Also, we use `generation_per_slot = 2^(-27)`. Notice that if any of those values are changed in the future, the formulas below in this TIP might become deprecated. Applying the simmplifications mentioned above, we have: - `Potential_Mana_0 = amount * d2 * 2^(-27) + 1154 * amount * 2^(-14)` - `Potential_Mana_n = amount * d1 * decay(n) * 2^(-k-27) ` - `Potential_Mana_n_1 = - 1154 * amount * decay(n-1) * 2^(-k-14)` -Analogously, we find formulas for `n<2:` +Analogously, we find formulas for `n < 2:` - If `n = 1`: `Potential_Mana = amount * d1 * decay(1) * 2^(-k-27) + amount * d2 * 2^(-27)` -- If `n = 0`: `Potential_Mana = amount * (consumption_slot-creation_slot) * 2^(-27)` +- If `n = 0`: `Potential_Mana = amount * (consumption_slot - creation_slot) * 2^(-27)` @@ -219,7 +219,7 @@ The exact order of the operations that must be done are defined in the next sect ``` if creation_decay_index == consumption_decay_index: - maxAmountValueToScale = uint64(2^51-1) + maxAmountValueToScale = uint64(2^51 - 1) bitsDecreased := 0 while amount > uint64(maxAmountValueToScale) { amount = amount >> 1 @@ -233,19 +233,19 @@ if creation_decay_index == consumption_decay_index: elif creation_decay_index + 1 == consumption_decay_index: d1 = slot_after_creation_decay_index - creation_slot d2 = consumption_slot - first_slot_consumption_decay_index - maxAmountValueToScale = uint64(2^51-1) + maxAmountValueToScale = uint64(2^51 - 1) bitsDecreased := 0 while amount > uint64(maxAmountValueToScale) { amount = amount >> 1 bitsDecreased++ } - potential_mana = amount * (d1*1023 + d2*1024) *2^(-(37- bitsDecreased)) + potential_mana = amount * (d1 * 1023 + d2 * 1024) * 2^(-(37 - bitsDecreased)) else: d1 = slot_after_creation_decay_index - creation_slot d2 = consumption_slot - first_slot_consumption_decay_index - potential_mana = amount *2^(-27) * 2^(-12)(d1*decay(n) + 4096 d2 +8380416*(4096-decay(n-1))) + potential_mana = amount * 2^(-27) * 2^(-12) * (d1 * decay(n) + 4096 * d2 + 8380416 * (4096 - decay(n - 1))) ``` @@ -334,7 +334,7 @@ if creation_decay_index == consumption_decay_index: new_mana_amount = mana_amount else: - maxManaValueToScale = uint64(2^52-1) + maxManaValueToScale = uint64(2^52 - 1) bitsDecreased := 0 while mana_amount > uint64(maxManaValueToScale) { mana_amount = mana_amount >> 1 @@ -387,7 +387,7 @@ It allows for the global control of the BIC dynamic with a Mana decay function. - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an decay index. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC, by applying: ``` if BIC > 0: - maxBICValueToScale = int64(2^51-1) + maxBICValueToScale = int64(2^51 - 1) bitsDecreased := 0 while BIC > maxBICValueToScale { BIC = BIC >> 1 @@ -491,7 +491,7 @@ Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA ## Lookup Table -
Lookup Table: Decays for Mana in decay index granularity scaled to 2^12
nTypedecay(n)
1 + uint16 4092
2 + uint16 4088
3 + uint16 4085
4 + uint16 4081
5 + uint16 4078
6 + uint16 4074
7 + uint16 4071
8 + uint16 4067
9 + uint16 4064
10 + uint16 4060
11 + uint16 4057
12 + uint16 4053
13 + uint16 4050
14 + uint16 4046
15 + uint16 4043
16 + uint16 4039
17 + uint16 4036
18 + uint16 4032
19 + uint16 4029
20 + uint16 4025
21 + uint16 4022
22 + uint16 4018
23 + uint16 4015
24 + uint16 4011
25 + uint16 4008
26 + uint16 4004
27 + uint16 4001
28 + uint16 3997
29 + uint16 3994
30 + uint16 3990
31 + uint16 3987
32 + uint16 3984
33 + uint16 3980
34 + uint16 3977
35 + uint16 3973
36 + uint16 3970
37 + uint16 3966
38 + uint16 3963
39 + uint16 3959
40 + uint16 3956
41 + uint16 3953
42 + uint16 3949
43 + uint16 3946
44 + uint16 3942
45 + uint16 3939
46 + uint16 3936
47 + uint16 3932
48 + uint16 3929
49 + uint16 3925
50 + uint16 3922
51 + uint16 3919
52 + uint16 3915
53 + uint16 3912
54 + uint16 3908
55 + uint16 3905
56 + uint16 3902
57 + uint16 3898
58 + uint16 3895
59 + uint16 3892
60 + uint16 3888
61 + uint16 3885
62 + uint16 3881
63 + uint16 3878
64 + uint16 3875
65 + uint16 3871
66 + uint16 3868
67 + uint16 3865
68 + uint16 3861
69 + uint16 3858
70 + uint16 3855
71 + uint16 3851
72 + uint16 3848
73 + uint16 3845
74 + uint16 3841
75 + uint16 3838
76 + uint16 3835
77 + uint16 3831
78 + uint16 3828
79 + uint16 3825
80 + uint16 3821
81 + uint16 3818
82 + uint16 3815
83 + uint16 3811
84 + uint16 3808
85 + uint16 3805
86 + uint16 3802
87 + uint16 3798
88 + uint16 3795
89 + uint16 3792
90 + uint16 3788
91 + uint16 3785
92 + uint16 3782
93 + uint16 3779
94 + uint16 3775
95 + uint16 3772
96 + uint16 3769
97 + uint16 3766
98 + uint16 3762
99 + uint16 3759
100 + uint16 3756
101 + uint16 3753
102 + uint16 3749
103 + uint16 3746
104 + uint16 3743
105 + uint16 3740
106 + uint16 3736
107 + uint16 3733
108 + uint16 3730
109 + uint16 3727
110 + uint16 3723
111 + uint16 3720
112 + uint16 3717
113 + uint16 3714
114 + uint16 3710
115 + uint16 3707
116 + uint16 3704
117 + uint16 3701
118 + uint16 3698
119 + uint16 3694
120 + uint16 3691
121 + uint16 3688
122 + uint16 3685
123 + uint16 3682
124 + uint16 3678
125 + uint16 3675
126 + uint16 3672
127 + uint16 3669
128 + uint16 3666
129 + uint16 3663
130 + uint16 3659
131 + uint16 3656
132 + uint16 3653
133 + uint16 3650
134 + uint16 3647
135 + uint16 3644
136 + uint16 3640
137 + uint16 3637
138 + uint16 3634
139 + uint16 3631
140 + uint16 3628
141 + uint16 3625
142 + uint16 3622
143 + uint16 3618
144 + uint16 3615
145 + uint16 3612
146 + uint16 3609
147 + uint16 3606
148 + uint16 3603
149 + uint16 3600
150 + uint16 3597
151 + uint16 3593
152 + uint16 3590
153 + uint16 3587
154 + uint16 3584
155 + uint16 3581
156 + uint16 3578
157 + uint16 3575
158 + uint16 3572
159 + uint16 3569
160 + uint16 3566
161 + uint16 3562
162 + uint16 3559
163 + uint16 3556
164 + uint16 3553
165 + uint16 3550
166 + uint16 3547
167 + uint16 3544
168 + uint16 3541
169 + uint16 3538
170 + uint16 3535
171 + uint16 3532
172 + uint16 3529
173 + uint16 3526
174 + uint16 3523
175 + uint16 3520
176 + uint16 3517
177 + uint16 3513
178 + uint16 3510
179 + uint16 3507
180 + uint16 3504
181 + uint16 3501
182 + uint16 3498
183 + uint16 3495
184 + uint16 3492
185 + uint16 3489
186 + uint16 3486
187 + uint16 3483
188 + uint16 3480
189 + uint16 3477
190 + uint16 3474
191 + uint16 3471
192 + uint16 3468
193 + uint16 3465
194 + uint16 3462
195 + uint16 3459
196 + uint16 3456
197 + uint16 3453
198 + uint16 3450
199 + uint16 3447
200 + uint16 3444
201 + uint16 3441
202 + uint16 3438
203 + uint16 3435
204 + uint16 3432
205 + uint16 3429
206 + uint16 3426
207 + uint16 3423
208 + uint16 3420
209 + uint16 3417
210 + uint16 3414
211 + uint16 3412
212 + uint16 3409
213 + uint16 3406
214 + uint16 3403
215 + uint16 3400
216 + uint16 3397
217 + uint16 3394
218 + uint16 3391
219 + uint16 3388
220 + uint16 3385
221 + uint16 3382
222 + uint16 3379
223 + uint16 3376
224 + uint16 3373
225 + uint16 3370
226 + uint16 3368
227 + uint16 3365
228 + uint16 3362
229 + uint16 3359
230 + uint16 3356
231 + uint16 3353
232 + uint16 3350
233 + uint16 3347
234 + uint16 3344
235 + uint16 3341
236 + uint16 3338
237 + uint16 3336
238 + uint16 3333
239 + uint16 3330
240 + uint16 3327
241 + uint16 3324
242 + uint16 3321
243 + uint16 3318
244 + uint16 3315
245 + uint16 3313
246 + uint16 3310
247 + uint16 3307
248 + uint16 3304
249 + uint16 3301
250 + uint16 3298
251 + uint16 3295
252 + uint16 3293
253 + uint16 3290
254 + uint16 3287
255 + uint16 3284
256 + uint16 3281
257 + uint16 3278
258 + uint16 3275
259 + uint16 3273
260 + uint16 3270
261 + uint16 3267
262 + uint16 3264
263 + uint16 3261
264 + uint16 3258
265 + uint16 3256
266 + uint16 3253
267 + uint16 3250
268 + uint16 3247
269 + uint16 3244
270 + uint16 3242
271 + uint16 3239
272 + uint16 3236
273 + uint16 3233
274 + uint16 3230
275 + uint16 3228
276 + uint16 3225
277 + uint16 3222
278 + uint16 3219
279 + uint16 3216
280 + uint16 3214
281 + uint16 3211
282 + uint16 3208
283 + uint16 3205
284 + uint16 3203
285 + uint16 3200
286 + uint16 3197
287 + uint16 3194
288 + uint16 3191
289 + uint16 3189
290 + uint16 3186
291 + uint16 3183
292 + uint16 3180
293 + uint16 3178
294 + uint16 3175
295 + uint16 3172
296 + uint16 3169
297 + uint16 3167
298 + uint16 3164
299 + uint16 3161
300 + uint16 3158
301 + uint16 3156
302 + uint16 3153
303 + uint16 3150
304 + uint16 3148
305 + uint16 3145
306 + uint16 3142
307 + uint16 3139
308 + uint16 3137
309 + uint16 3134
310 + uint16 3131
311 + uint16 3129
312 + uint16 3126
313 + uint16 3123
314 + uint16 3120
315 + uint16 3118
316 + uint16 3115
317 + uint16 3112
318 + uint16 3110
319 + uint16 3107
320 + uint16 3104
321 + uint16 3102
322 + uint16 3099
323 + uint16 3096
324 + uint16 3093
325 + uint16 3091
326 + uint16 3088
327 + uint16 3085
328 + uint16 3083
329 + uint16 3080
330 + uint16 3077
331 + uint16 3075
332 + uint16 3072
333 + uint16 3069
334 + uint16 3067
335 + uint16 3064
336 + uint16 3062
337 + uint16 3059
338 + uint16 3056
339 + uint16 3054
340 + uint16 3051
341 + uint16 3048
342 + uint16 3046
343 + uint16 3043
344 + uint16 3040
345 + uint16 3038
346 + uint16 3035
347 + uint16 3032
348 + uint16 3030
349 + uint16 3027
350 + uint16 3025
351 + uint16 3022
352 + uint16 3019
353 + uint16 3017
354 + uint16 3014
355 + uint16 3012
356 + uint16 3009
357 + uint16 3006
358 + uint16 3004
359 + uint16 3001
360 + uint16 2999
361 + uint16 2996
362 + uint16 2993
363 + uint16 2991
364 + uint16 2988
365 + uint16 2986
+
Lookup Table: Decays for Mana in decay index granularity scaled to 2^12
From 80022eb1e79e5aa8b447ad65d877bbd3b495fd2c Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 11 Jul 2023 12:57:55 +0200 Subject: [PATCH 042/157] Minor changes --- tips/TIP-0039/tip-0039.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 7227346a1..337a1e679 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -159,12 +159,11 @@ Analogously, if `n ≤ 1`, we find the following results (here `δ` is the diffe The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated `2^k * exp(-β * Δ * i)` by `decay(i)`, where `k` is the precision of the Lookup table used: -- If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))`. Then, `Potential_Mana = Potential_Mana_0 + Potential_Mana_n + Potential_Mana_n_1`, where: - - `Potential_Mana_0 = amount * generation_per_slot * d2 + c * amount * generation_per_slot * slots_per_decay_index` - - `Potential_Mana_n = amount * generation_per_slot * d1 * decay(n) * 2^(-k) ` - - `Potential_Mana_n_1 = - c * amount * generation_per_slot * slots_per_decay_index * decay(n-1) * 2^(-k)` - - and +If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))`. Then, `Potential_Mana = Potential_Mana_0 + Potential_Mana_n + Potential_Mana_n_1`, where: + - `Potential_Mana_0 = amount * generation_per_slot * d2 + c * amount * generation_per_slot * slots_per_decay_index`; + - `Potential_Mana_n = amount * generation_per_slot * d1 * decay(n) * 2^(-k) `; + - `Potential_Mana_n_1 = - c * amount * generation_per_slot * slots_per_decay_index * decay(n-1) * 2^(-k)`; +and - `slots_per_decay_index` is the number of slots in a decay index - `d1 = slot_after_decay_index_i - creation_slot` - `slot_after_decay_index_i` is the first slot of the decay index `i + 1` ; @@ -173,7 +172,7 @@ The formulas found in the last section are the exact formulas for the model prop - `generation_per_slot` is the Mana generated by holding 1 IOTA for 1 slot. We begin by applying to the formulas above some of the protocol parameters. Specifically, we use that -- `β= 1/3` per year; +- `β = 1/3` per year; - `slots_per_decay_index = 2^13`; - Duration of a slot is 10 seconds. This means that the duration of a decay index in years is around `Δ = 0.002597666159`. From 8524ec7fb2060e0d4d45ba584e45eb552844fac3 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 11 Jul 2023 12:58:36 +0200 Subject: [PATCH 043/157] Minor change --- tips/TIP-0039/tip-0039.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 337a1e679..0f8c78ded 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -163,6 +163,7 @@ If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(- - `Potential_Mana_0 = amount * generation_per_slot * d2 + c * amount * generation_per_slot * slots_per_decay_index`; - `Potential_Mana_n = amount * generation_per_slot * d1 * decay(n) * 2^(-k) `; - `Potential_Mana_n_1 = - c * amount * generation_per_slot * slots_per_decay_index * decay(n-1) * 2^(-k)`; + and - `slots_per_decay_index` is the number of slots in a decay index - `d1 = slot_after_decay_index_i - creation_slot` From 57c08007b9171f4eaa54c9d8dab5cacfc36a5a92 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 11 Jul 2023 13:00:09 +0200 Subject: [PATCH 044/157] Fix indentation --- tips/TIP-0039/tip-0039.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 0f8c78ded..528ddcab3 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -160,17 +160,17 @@ Analogously, if `n ≤ 1`, we find the following results (here `δ` is the diffe The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated `2^k * exp(-β * Δ * i)` by `decay(i)`, where `k` is the precision of the Lookup table used: If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))`. Then, `Potential_Mana = Potential_Mana_0 + Potential_Mana_n + Potential_Mana_n_1`, where: - - `Potential_Mana_0 = amount * generation_per_slot * d2 + c * amount * generation_per_slot * slots_per_decay_index`; - - `Potential_Mana_n = amount * generation_per_slot * d1 * decay(n) * 2^(-k) `; - - `Potential_Mana_n_1 = - c * amount * generation_per_slot * slots_per_decay_index * decay(n-1) * 2^(-k)`; +- `Potential_Mana_0 = amount * generation_per_slot * d2 + c * amount * generation_per_slot * slots_per_decay_index`; +- `Potential_Mana_n = amount * generation_per_slot * d1 * decay(n) * 2^(-k) `; +- `Potential_Mana_n_1 = - c * amount * generation_per_slot * slots_per_decay_index * decay(n-1) * 2^(-k)`; and - - `slots_per_decay_index` is the number of slots in a decay index - - `d1 = slot_after_decay_index_i - creation_slot` - - `slot_after_decay_index_i` is the first slot of the decay index `i + 1` ; - - `d2 = consumption_slot - first_slot_decay_index_j` - - `first_slot_decay_index_j` is the first slot of decay index `j` ; - - `generation_per_slot` is the Mana generated by holding 1 IOTA for 1 slot. +- `slots_per_decay_index` is the number of slots in a decay index +- `d1 = slot_after_decay_index_i - creation_slot` +- `slot_after_decay_index_i` is the first slot of the decay index `i + 1` ; +- `d2 = consumption_slot - first_slot_decay_index_j` +- `first_slot_decay_index_j` is the first slot of decay index `j` ; +- `generation_per_slot` is the Mana generated by holding 1 IOTA for 1 slot. We begin by applying to the formulas above some of the protocol parameters. Specifically, we use that - `β = 1/3` per year; From cfff01bdd29b9cd85036bd5533847877518ac646 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Thu, 20 Jul 2023 18:23:34 +0100 Subject: [PATCH 045/157] update fixed point calculations --- tips/TIP-0039/tip-0039.md | 1788 +++++++++++++++++++------------------ 1 file changed, 905 insertions(+), 883 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 528ddcab3..399268106 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -97,41 +97,106 @@ Mana decay is introduced as a control mechanism of the Mana dynamics, altogether As the form in which the decay factor will be applied might differ between the Mana types, it is essential to point out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. -Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every`8192` slots, the epoch changes, meaning that every set of consecutive `2^(13)` slots will be in the same epoch. +Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every`2^(slotsPerEpochExponent)` slots, the epoch changes, meaning that every set of consecutive `2^(slotsPerEpochExponent)` slots will be in the same epoch. We set `slotsPerEpochExponent = 13`. -The decay parameter `β` (together with the Mana generation parameter) were set so the maximum theoretical Mana in the system is `2^53 - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses 53 bits (in the case of BIC, it uses 54 bits, 53 for the value and one for the sign). Notice that this value of `2^53 - 1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^53 - 1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. +The decay parameter `β` (together with the Mana generation parameter) were set so the maximum theoretical Mana in the system is `2^53 - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses 53 bits (in the case of BIC, it uses at most 54 bits, 53 for the value and one for the sign). Notice that this value of `2^53 - 1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^53 - 1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. + +==TO DO: check if it's really 53 bits== ## Mana and fixed point arithmetics Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding behavior in different architectures. The results of the operations involving floating point variables might differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, differences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviors in the system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. -We introduce in the last section of this TIP a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^12 * exp(-β * Decay Index Duration * n)`, where `β` and `Decay Index Duration` are protocol parameters, for different values of `n`. +We introduce in the last section of this TIP a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^(decayFactorsExponent) * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, for different values of `n`. We set `decayFactorsExponent = 32`, `epochDuration = 10*2^(slotsPerEpochExponent) = 10*2^13` seconds (which means that the duration of an epoch in years is around `0.002597666159`), and `β = 1/3` per year. + ### How to use the lookup table -==TO DO: decide to max decay index in the table== +==TO DO: decide to max epoch in the table, if it's 365 or if we are adding values per year in the end== -The table defined above only gives the values of `decay(n)` for some values of `n` up to 365. To calculate `decay(n)` for larger values of `n`, we combine values of decays for other numbers smaller than 365, using the following algorithm: +In this section we define a function `decay(value, n)`, that decays an amount on Mana `value` by the factor relative to `n` epochs. Notice that the table defined above only gives the values of `lookupTable(n)` for some values of `n` up to `maxDecayFactor = 365`. To calculate `decay(value, n)` for larger values of `n`, we combine values defined in the lookup table for other numbers smaller than 365, using an algorithm that will be defined below. First, we define three auxiliary functions: + +``` +// Returns the upper n bits of a uint64 value +func upperBits(value, n){ + value = value >> n + return value +} +``` -- If `n > 365`: Let `n/365` be an integer division (e.g., `367/365 = 1`) and `n mod 365` be the module operation (e.g., `367 mod 365 = 2`). - ``` -value = uint32(2^12) -for i = 1,...,n/365: - value = [value * decay(365)] >> 12 -value = [value * decay(n mod 365)] >> 12 +// Returns the upper n bits of a uint64 value +func lowerBits(value, n){ + value = value << (64-n) + value = value >> (64-n) + return value +} ``` -Notice that since the values in the table smaller than `2^12`, the multiplications in the algorithm have to be done using a `uint32` variable to avoid overflowing. The final result can be stored as a `uint16` value (if needed), since after the final shift operation the result will be smaller than `2^12` again. +``` +// Returns the result of the multiplication ((valueHi<<32+valueLo)*multFactor)>>shiftFactor +// (where multFactor is a uint32, valueHi and valueLo are uint64 smaller than 2^32, and 0<=shiftFactor<=32), +// using only uint64 multiplication functions, without overflowing. The returned result is split in 2 factors: +// valueHi and valueLo, one containing the upper 32 bits of the result and the other containing the lower 32 bits. +func MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor) (uint64, uint64) { + // multiply the integer part of valueHi by multFactor + valueHi = valueHi * multFactor + + // the lower shiftFactor bits of the result are extracted and shifted left to form the remainder. + // valueLo is multiplied by multFactor and right-shifted by shiftFactor bits. + // the sum of these two values forms the new lower part (valueLo) of the result. + valueLo = lowerBits(valueHi,shiftFactor)<<(32-shiftFactor) + (valueLo*multFactor)>>shiftFactor + + // the right-shifted valueHi and the upper 32 bits of valueLo form the new higher part (valueHi) of the result. + valueHi = (valueHi >> shiftFactor) + upperBits(valueLo,32) + + // the lower 32 bits of valueLo form the new lower part of the result. + valueLo = lowerBits(valueLo,32) + + // return the result as a fixed-point number composed of two 64-bit integers + return valueHi, valueLo +} +``` -- If `n = 0`, `exp(-β * Decay Index Duration * n) = 1`. Thus, in this case, the decay (and the lookup table) should not be applied. +With the functions above defined, we procceed to define the `decay` funtion, that takes as input a uint64 valuable `value`and decays it by the correct decay factor, relative to `n` epochs. -Other implementations of the function are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and multiplications with integers might lead to different results when the order is altered. -Example: suppose one needs to calculate `1002*99/100*21/100`. Following the left-to-right order, this would result in `1002*99/100*21/100 = 99198/100*21/100 = 991*21/100 = 20811/100 = 208`. If someone did this operation in a different order, let's say `1002*21/100*99/100`, the result would be `1002*21/100*99/100 = 21042/100*99/100 = 210*99/100 = 20790/100 = 207`. +``` +func decay(value, n) { + if value == 0 or n == 0 { + return value + } + + // split the value into two uint64 variables to prevent overflowing + valueHi = upperBits(value,32) + valueLo = lowerBits(value,32) + + // we keep applying the lookup table factors as long as n epochs are left + remainingEpochs = n + while remainingEpochs > 0 { + EpochsToDecay = remainingEpochs + if EpochsToDecay > maxDecayFactor { + EpochsToDecay = maxDecayFactor + } + remainingEpochs -= EpochsToDecay + + decayFactor = lookupTable(EpochsToDecay) + + // apply the decay using fixed-point arithmetics. + valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, decayFactor, decayFactorsExponent) + } + // combine both uint64 variables to get the actual value + return valueHi<<32 + valueLo +} +``` + +Other implementations of the functions above are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and multiplications with integers might lead to different results when the order is altered. +Example: suppose one needs to calculate `1002*99/100*21/100`. Following the left-to-right order, this would result in `1002*99/100*21/100 = 99198/100*21/100 = 991*21/100 = 20811/100 = 208`. If someone did this operation in a different order, let's say `1002*21/100*99/100`, the result would be `1002*21/100*99/100 = 21042/100*99/100 = 210*99/100 = 20790/100 = 207`. ## Potential Mana +==TO DO : check if storage deposit ctually generate mana== + *Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token, whether storage deposit or not, generates potential Mana. The view on the potential Mana value can be deterministically derived from the UTXO ledger, @@ -139,13 +204,13 @@ based on the UTXO IOTA token value and the time it was created in the UTXO metad ### Rationale behind the Potential Mana formulas -We model the potential Mana generated by an output holding `S` IOTA tokens as the combination of a fixed generation per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time a decay index ends, where `Δ` is the decay index duration. +We model the potential Mana generated by an output holding `S` IOTA tokens as the combination of a fixed generation per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time an epochends, where `Δ` is the epoch duration. ![](https://hackmd.io/_uploads/Bkzz3PiD2.png) FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW -Let `i` be the decay index of the creation slot and `j` be the decay index of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in decay index `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in decay index `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n - 1` times, and so on, until the Mana generated in decay index `j`, which is not decayed at all. Adding these values, we find the following formulas (here `d` is the number of slots in a decay index): +Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in epoch `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in epoch `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n - 1` times, and so on, until the Mana generated in epoch `j`, which is not decayed at all. Adding these values, we find the following formulas (here `d` is the number of slots in a epoch): `Potential Mana = γ * S * [d1 * exp(-β * Δ * n) + d * exp(-β * Δ * (n - 1)) + d * exp(-β * Δ * (n - 2)) + ... + d * exp(-β * Δ) + d2] = γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = @@ -157,56 +222,34 @@ Analogously, if `n ≤ 1`, we find the following results (here `δ` is the diffe ### Potential Mana formulas with fixed point arithmetics -The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated `2^k * exp(-β * Δ * i)` by `decay(i)`, where `k` is the precision of the Lookup table used: +The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated `2^decayFactorsExponent * exp(-β * Δ * i)` by `lookupTable(i)`, where `decayFactorsExponent` is the precision of the Lookup table used: -If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))`. Then, `Potential_Mana = Potential_Mana_0 + Potential_Mana_n + Potential_Mana_n_1`, where: -- `Potential_Mana_0 = amount * generation_per_slot * d2 + c * amount * generation_per_slot * slots_per_decay_index`; -- `Potential_Mana_n = amount * generation_per_slot * d1 * decay(n) * 2^(-k) `; -- `Potential_Mana_n_1 = - c * amount * generation_per_slot * slots_per_decay_index * decay(n-1) * 2^(-k)`; +If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form `c = decayFactorEpochsSum*2^(-decayFactorEpochsSumExponent)`. Given the values defined in the last section, we set `decayFactorEpochsSum=` and `decayFactorEpochsSumExponent=`. Then, `Potential_Mana = aux + aux1 + aux2`, where: +- `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; +- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-decayFactorsExponent) `; +- `aux2 = - c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n-1)+1) * 2^(-decayFactorsExponent)`; and -- `slots_per_decay_index` is the number of slots in a decay index -- `d1 = slot_after_decay_index_i - creation_slot` -- `slot_after_decay_index_i` is the first slot of the decay index `i + 1` ; -- `d2 = consumption_slot - first_slot_decay_index_j` -- `first_slot_decay_index_j` is the first slot of decay index `j` ; -- `generation_per_slot` is the Mana generated by holding 1 IOTA for 1 slot. +- `slotPerEpoch = 2^slotsPerEpochExponent` is the number of slots in an epoch. Initially, we use `slotsPerEpochExponent = 13`. +- `d1 = slotAfterEpochi - creationSlot` +- `slotAfterEpochi` is the first slot of the epoch `i + 1` ; +- `d2 = consumptionSlot - firstSlotEpochJ` +- `firstSlotEpochJ` is the first slot of epoch `j` ; +- `generationPerSlot = generationRate * 2^(-generationRateExponent)` is the Mana generated by holding 1 IOTA for 1 slot. Initially, we use `generationRate = 1` and `generationRateExponent=27`. -We begin by applying to the formulas above some of the protocol parameters. Specifically, we use that -- `β = 1/3` per year; -- `slots_per_decay_index = 2^13`; -- Duration of a slot is 10 seconds. This means that the duration of a decay index in years is around `Δ = 0.002597666159`. - -With the values above, we approximate `c = 1154`. Also, we use `generation_per_slot = 2^(-27)`. Notice that if any of those values are changed in the future, the formulas below in this TIP might become deprecated. Applying the simmplifications mentioned above, we have: -- `Potential_Mana_0 = amount * d2 * 2^(-27) + 1154 * amount * 2^(-14)` -- `Potential_Mana_n = amount * d1 * decay(n) * 2^(-k-27) ` -- `Potential_Mana_n_1 = - 1154 * amount * decay(n-1) * 2^(-k-14)` - -Analogously, we find formulas for `n < 2:` -- If `n = 1`: `Potential_Mana = amount * d1 * decay(1) * 2^(-k-27) + amount * d2 * 2^(-27)` -- If `n = 0`: `Potential_Mana = amount * (consumption_slot - creation_slot) * 2^(-27)` - - - -# MAX, IT'S GOOD UNTIL THIS POINT - - -The exact order of the operations that must be done are defined in the next section. - - - - - - - - - - - +Note that the term `aux2` has a factor `lookupTable(n-1)+1` instead of `lookupTable(n-1)` since the values in the lookup table are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing this, we avoid potential gameability scenarios, since all the terms added will be rounded by below in the formula. +Rearranging the formuals above, we have that `Potential_Mana = potentialMana0 + potentialManan + potentialManan1`, where +- `potentialMana0 = amount * d2 * generationRate * 2^(-generationRateExponent) + c * amount * generationRate * 2^(slotsPerEpochExponent-generationRateExponent)- c * amount * generationRate * 2^(slotsPerEpochExponent-decayFactorsExponent-generationRateExponent)` +- `potentialManan = amount * d1 * lookupTable(n) * generationRate * 2^(-decayFactorsExponent-generationRateExponent) ` +- `potentialManan1 = - c * amount * generationRate * lookupTable(n-1) * 2^(slotsPerEpochExponent-decayFactorsExponent-generationRateExponent)` +Analogously, we find formulas for `n < 2:` +- If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * generationRate * 2^(-decayFactorsExponent-generationRateExponent) + amount * d2 * generationRate * 2^(-generationRateExponent)` +- If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * generationRate * 2^(-generationRateExponent)` +In the next section, we introduce the defaut implementation for the formulas presented above. ### Potential Mana Semantic Validation - Potential Mana must and can only be consumed when the corresponding output is consumed. @@ -214,42 +257,9 @@ The exact order of the operations that must be done are defined in the next sect - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. -- The exact algorithm to calculate the Potential Mana generated by an output created at slot `creation_slot` (which has a decay index `creation_decay_index`) and consumed at slot `consumption_slot` (which has a decay index `consumption_decay_index`), holding `Amount` IOTA tokens, is given by (again, in the pseudocode below, `slot_after_creation_decay_index` is the first slot of the decay index after the creation decay index and `first_slot_consumption_decay_index` is the first slot of the consumption decay index): - ==to do: fix the operations below so it does not overflow== +- The exact algorithm to calculate the Potential Mana generated by an output created at slot `creationSlot` (which has an epoch`creationEpoch`) and consumed at slot `consumptionSlot` (which has an epoch`consumptionEpoch`), holding `Amount` IOTA tokens, is given by (again, in the pseudocode below, `slotAfterCreationEpoch` is the first slot of the epoch after the creation epoch and `firstSlotConsumptionEpoch` is the first slot of the consumption epoch) the algorithms define below. -``` -if creation_decay_index == consumption_decay_index: - maxAmountValueToScale = uint64(2^51 - 1) - bitsDecreased := 0 - while amount > uint64(maxAmountValueToScale) { - amount = amount >> 1 - bitsDecreased++ - } - - potential_mana = amount * (consumption_slot - creation_slot) - potential_mana = potential_mana >> 27 - bitsDecreased - - -elif creation_decay_index + 1 == consumption_decay_index: - d1 = slot_after_creation_decay_index - creation_slot - d2 = consumption_slot - first_slot_consumption_decay_index - maxAmountValueToScale = uint64(2^51 - 1) - bitsDecreased := 0 - while amount > uint64(maxAmountValueToScale) { - amount = amount >> 1 - bitsDecreased++ - } - - potential_mana = amount * (d1 * 1023 + d2 * 1024) * 2^(-(37 - bitsDecreased)) - -else: - d1 = slot_after_creation_decay_index - creation_slot - d2 = consumption_slot - first_slot_consumption_decay_index - potential_mana = amount * 2^(-27) * 2^(-12) * (d1 * decay(n) + 4096 * d2 + 8380416 * (4096 - decay(n - 1))) - - -``` - +
Lookup Table: Decays for Mana in decay index granularity scaled to `2^12`
n Type
@@ -257,21 +267,21 @@ else: - + - + - +
NameDescription
AmountValue uint64 The amount of IOTA tokens held in the output.
Creation SlotcreationSlot uint64 The index of slot in which the output was created.
Consumption SlotconsumptionSlot uint64 The index of slot in which the output is consumed. @@ -279,6 +289,44 @@ else:
+ +==To do: talk about the missing remainder== + + +We begin by defining an auxiliary function that (intuitively) generates Mana without applying any type of decay (note that we use some of the functions and constants defined in the last sections): + +``` +// generateMana calculates the generated mana from holding `value` tokens for `m` slots, without applying any decay. +func generateMana(value, m) { + if m == 0 or generationRate == 0 { + return 0 + } + return MultiplicationAndShift(value, m*generationRate, generationRateExponent) +} +```` + +Now we define the function that actually calculates the Potential Mana using the formulas defined in the last section (including the decays). Let `n=consumptionSlot-creationSlot`, `d1=slotAfterCreationEpoch-creationSlot`, and `d2=consumptionSlot-firstSlotConsumptionEpoch`. Then, we have: + +``` +// PotentialManaWithDecay calculates the generated potential mana and applies the decay to the result. +func PotentialManaWithDecay(value, n, d1, d2) { + if n == 0: + return generateMana(value, d1+d2-2^slotsPerEpochExponent) + else if n == 1: + return decay(generateMana(value, d1), 1) + generateMana(value, d2) + else: + aux = MultiplicationAndShift(value*generationRate, decayFactorEpochsSum, decayFactorEpochsSumExponent+generationRateExponent-slotsPerEpochExponent) + + potentialMana_n := decay(generateMana(value, d1), n) + potentialMana_n_1 := decay(aux, n-1) + potentialMana_0 := generateMana(value, d2) + aux - aux>>decayFactorsExponent + + return potentialMana_n - potentialMana_n_1 + potentialMana_0 + } +``` + +==to do: talk with max about the generationRate in aux and generateMana== + ## Stored Mana *Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA tokens) of Mana that can be transferred within certain rules between different users, which allows for Mana market development. @@ -295,7 +343,7 @@ This field represents the amount of stored Mana at the output's creation time un - The decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. - To calculate the decay of stored Mana, the creation time of each output with stored Mana must be contained in transactions. - The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: - - Let `Mana Amount`, `Consumption Slot`, and `Creation Slot`, be + - Let `manaAmount`, `consumptionSlot`, and `creationSlot`, be @@ -304,21 +352,21 @@ This field represents the amount of stored Mana at the output's creation time un - + - + - +
Description
Mana AmountmanaAmount uint64 The amount of stored Mana held by the output.
Creation SlotcreationSlot uint64 The index of slot in which the output was created.
Consumption SlotconsumptionSlot uint64 The index of slot in which the output is consumed. @@ -327,22 +375,16 @@ This field represents the amount of stored Mana at the output's creation time un
The algorithm to decay the stored Mana is as follows + + + ``` -creation_decay_index = decay_index(creation_slot) -consumption_decay_index = decay_index(consumption_slot) -if creation_decay_index == consumption_decay_index: - new_mana_amount = mana_amount - +creationEpoch = epoch(creationSlot) +consumptionEpoch = epoch(consumptionSlot) +if creationEpoch == consumptionEpoch: + newManaAmount = manaAmount else: - maxManaValueToScale = uint64(2^52 - 1) - bitsDecreased := 0 - while mana_amount > uint64(maxManaValueToScale) { - mana_amount = mana_amount >> 1 - bitsDecreased++ - } - - new_mana_amount = mana_amount * decay(consumption_decay_index - creation_decay_index) - new_mana_amount = new_mana_amount >> (12 - bitsDecreased) + newManaAmount = decay(manaAmount,consumptionEpoch-creationEpoch) ``` @@ -369,7 +411,7 @@ Using account IDs for that purpose is thus a good fit. Consequently, the ledger state is not bloated by having to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that requires a storage deposit in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the block issuance credits. - A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. - - The end time of an decay index is used for the decay calculations. + - The end time of an epoch is used for the decay calculations. - Definition of slots based on the time of the genesis slot and slot duration. - A commitment mechanism per slot is needed to ensure the unified perception of the BIC in the longer run. - The global agreement on the BIC balances among all the nodes is required. @@ -380,27 +422,21 @@ It allows for the global control of the BIC dynamic with a Mana decay function. - This decrease is also applied to the potential and stored Mana (that can be allotted to the account as BIC) so users cannot gain by delaying or advancing the allotting. - The balance of the BIC vector at the slot commitment must be the sum of: - The balances of the previously committed BIC vector. - - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of only decaying the BIC vector at the end of each decay index, this Mana would have to be decayed by a factor proportional to the difference between the transaction slot index and the index of the last slot of the decay index. However, since the decay rate is small, this difference will be always smaller than half a percent. We understand that this difference (since it's not composable and can only be "taken profit of" once) does not justify the user experience-related issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being allotted in a transaction. + - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of only decaying the BIC vector at the end of each epoch, this Mana would have to be decayed by a factor proportional to the difference between the transaction slot index and the index of the last slot of the epoch. However, since the decay rate is small, this difference will be always smaller than half a percent. We understand that this difference (since it's not composable and can only be "taken profit of" once) does not justify the user experience-related issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being allotted in a transaction. - Subtract from BIC all Mana burned by accepted blocks of the committed slots. -- BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the end of the decay index. -- Mana decay must be applied at the end of decay index according to the algorithm: - - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an decay index. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC, by applying: +- BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the end of the epoch. +- Mana decay must be applied at the end of epoch according to the algorithm: + - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an epoch. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC, by applying: + ``` if BIC > 0: - maxBICValueToScale = int64(2^51 - 1) - bitsDecreased := 0 - while BIC > maxBICValueToScale { - BIC = BIC >> 1 - bitsDecreased++ - } - new_BIC = BIC * decay(1) - new_BIC = new_BIC >> (12 - bitsDecreased) + new_BIC = decay(BIC,1) else: new_BIC = BIC ``` -If `i` is not the last slot of athe decay index, this decay should not be applied. +If `i` is not the last slot of the epoch, this decay should not be applied. - A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. @@ -422,7 +458,7 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra - Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. - Mana rewards must be put on outputs as stored Mana on the output side of the transaction. - The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: - - Let `Reward`, `Reward Epoch`, `Reward Decay Index` and `Claiming Slot Decay Index` be as follows: + - Let `reward`, `rewardEpoch`, and `claimingSlotEpoch` be as follows: @@ -430,49 +466,35 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra - + - + - + - - - - -
NameDescription
Rewardreward uint64 The amount of Mana rewards available to be claimed for staking or delegation for a specific epoch.
Rewards EpochrewardEpoch uint64 The index of the epoch for which Mana rewards are claimed.
Reward Decay IndexclaimingSlotEpoch uint64 - The decay index of the last slot in Rewards Epoch. -
Claiming Slot Decay Indexuint64 - The decay index of the slot in which the Mana rewards are claimed. + The epoch of the slot in which the Mana rewards are claimed.
- - Let `n = Claiming Slot Decay Index - Reward Decay Index`. If `n > 0`, with the aid of the lookup table and the algorithm defined in the section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the rewards, by applying: + - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the lookup table and the algorithm defined in the section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the rewards, by applying: ``` - maxRewardValueToScale = int64(2^52) - bitsDecreased := 0 - while Reward > maxRewardValueToScale { - Reward = Reward >> 1 - bitsDecreased++ - } - Reward = Reward * decay(n) - Reward = Reward >> (12 - bitsDecreased) + reward = decay(reward,n) ``` - - If `n = 0`, the amount to be put on outputs is the entire `Reward`. + - If `n = 0`, the amount to be put on outputs is the entire `reward`. @@ -490,8 +512,7 @@ Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA ## Lookup Table - - +
Lookup Table: Decays for Mana in decay index granularity scaled to `2^12`
@@ -499,1831 +520,1832 @@ Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + + # Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 665b8e84d9c3c6c0d3f9e64f0849ca2c21202518 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Thu, 27 Jul 2023 10:22:23 +0100 Subject: [PATCH 046/157] parametrization of the mana generation rate --- tips/TIP-0039/tip-0039.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 399268106..81268f4e8 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -99,9 +99,8 @@ As the form in which the decay factor will be applied might differ between the M Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every`2^(slotsPerEpochExponent)` slots, the epoch changes, meaning that every set of consecutive `2^(slotsPerEpochExponent)` slots will be in the same epoch. We set `slotsPerEpochExponent = 13`. -The decay parameter `β` (together with the Mana generation parameter) were set so the maximum theoretical Mana in the system is `2^53 - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses 53 bits (in the case of BIC, it uses at most 54 bits, 53 for the value and one for the sign). Notice that this value of `2^53 - 1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^53 - 1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. +The decay parameter `β` (together with the Mana generation parameter) was set so the maximum theoretical Mana in the system is `2^manaBits - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses `manaBits<64` bits (in the case of BIC, it uses at most `manaBits+1` bits, `manaBits` for the value and one for the sign). Notice that this value of `2^manaBits - 1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^manaBits - 1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. -==TO DO: check if it's really 53 bits== ## Mana and fixed point arithmetics @@ -235,7 +234,8 @@ and - `slotAfterEpochi` is the first slot of the epoch `i + 1` ; - `d2 = consumptionSlot - firstSlotEpochJ` - `firstSlotEpochJ` is the first slot of epoch `j` ; -- `generationPerSlot = generationRate * 2^(-generationRateExponent)` is the Mana generated by holding 1 IOTA for 1 slot. Initially, we use `generationRate = 1` and `generationRateExponent=27`. +- `generationPerSlot = generationRate * 2^(-generationRateExponent)` is the Mana generated by holding 1 IOTA for 1 slot. Initially, we use `generationRate = 1` and `generationRateExponent=80-manaBits`. This generation rate per slot guarantees that the maximum theoretical mana in the system uses the `manaBits` available bits; +- `manaBits = 63`. Note that the term `aux2` has a factor `lookupTable(n-1)+1` instead of `lookupTable(n-1)` since the values in the lookup table are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing this, we avoid potential gameability scenarios, since all the terms added will be rounded by below in the formula. From 8e4a7ca6faed99eb04e9a0ce31b7e19fbbfa3c06 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Mon, 31 Jul 2023 10:11:01 +0200 Subject: [PATCH 047/157] Fixing formatting, typos --- tips/TIP-0039/tip-0039.md | 133 ++++++++++++++++++++++++++------------ 1 file changed, 92 insertions(+), 41 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 81268f4e8..3beabfa9a 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -38,11 +38,21 @@ requires: TIP-42 # Summary This document defines the Mana-related concepts and the Mana dynamics in the IOTA 2.0 protocol. -The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana,** as well as the **Block Issuance Credit (BIC)** that Mana can be allotted to. +The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana,** as well as the +**Block Issuance Credit (BIC)** that Mana can be allotted to. # Motivation -Mana is a resource used to determine the allowed throughput of a user and as a payment form for block issuance in the Mana burn mechanism. -Mana can be obtained by helpful and profitable actions for the network, like token holding or engagement in securing the network. Additionally, owning Mana is necessary to use the network by issuing blocks, so it plays the core role in the IOTA tokenomics. The following document gives a high-level overview of Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation, and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of Mana is burned in each block, which is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to their account to increase their BIC and ensure it does not go negative. In order to issue blocks, allot Mana, and fully use all the Mana functionalities, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). +Mana is a resource used to determine the allowed throughput of a user and as a payment form for block issuance +in the Mana burn mechanism. Mana can be obtained by helpful and profitable actions for the network, like token +holding or engagement in securing the network. Additionally, owning Mana is necessary to use the network by issuing +blocks, so it plays the core role in the IOTA tokenomics. The following document gives a high-level overview of +Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, +delegation, and congestion control changes. This document works with the Congestion Control Algorithm with Mana +Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of Mana is burned in each +block, which is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to +their account to increase their BIC and ensure it does not go negative. In order to issue blocks, allot Mana, and +fully use all the Mana functionalities, the user is required to have an account, which is introduced in +[TIP-42](../TIP-0042/tip-0042.md). # Building Blocks @@ -58,64 +68,105 @@ It is an essential element of the IOTA protocol, as it is used to: * as a payment form for the block issuance. The following solutions are designed around the newest IOTA Congestion Control Algorithm (ICCA) with Mana Credits. -Additionally, Mana implementation is strictly connected to the accounts introduced in [TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivization scheme. +Additionally, Mana implementation is strictly connected to the accounts introduced in +[TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivization scheme. **Mana** can have different forms, each of which is described in the following sections. - -* [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved within certain rules between the different owners, which allows for Mana market development. -* [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. -It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. -* When the user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit form -(the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If a user does not store the potential Mana when consuming the output, she will forfeit this Mana. Alternatively, the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). -* [**Mana rewards**](#mana-rewards) are used to reward for participation in staking for validation and delegating IOTA tokens. The Mana rewarded from staking and validation must be claimed and stored as stored Mana. + * [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved +within certain rules between the different owners, which allows for Mana market development. + * [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. +It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO +that holds the IOTA tokens. + * When the user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit +form (the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If a user does not store +the potential Mana when consuming the output, she will forfeit this Mana. Alternatively, the user can convert Mana +to [**Block Issuance Credit**](#block-issuance-credit) (BIC). + * [**Mana rewards**](#mana-rewards) are used to reward for participation in staking for validation and delegating IOTA +tokens. The Mana rewarded from staking and validation must be claimed and stored as stored Mana. The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. ## Mana burn -According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a certain amount of Mana dictated by the size of the block and the Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Therefore, in order to prevent being locked out of their account, the block issuer must ensure that sufficient Mana is also allotted to their account to ensure their BIC balance remains non-negative. +According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a +certain amount of Mana dictated by the size of the block and the Reference Mana Cost (RMC). The Mana burned by the +block is subtracted from the block issuer's BIC balance. Therefore, in order to prevent being locked out of their +account, the block issuer must ensure that sufficient Mana is also allotted to their account to ensure their BIC +balance remains non-negative. ### Reference Mana Cost *Reference Mana Cost (RMC)* is used to decide how much Mana should be burned from BIC by each block in that slot. -RMC is computed according to an algorithm based on recent traffic activity: the algorithm counts the number of blocks in slots that are *Maximum Committable Age (MCA)* slots in the past so that all nodes agree on that value of RMC and know this value in advance (before issuing the block). +RMC is computed according to an algorithm based on recent traffic activity: the algorithm counts the number of +blocks in slots that are *Maximum Committable Age (MCA)* slots in the past so that all nodes agree on that value of +RMC and know this value in advance (before issuing the block). From a high-level perspective, the RMC algorithm works as follows: -- If the number of blocks in slot `i - MCA` is larger than a given threshold, then the RMC increases. -- Otherwise, if the activity is low, the RMC decreases. -- The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes too large for the majority of users, and activity drops. + * If the number of blocks in slot `i - MCA` is larger than a given threshold, then the RMC increases. + * Otherwise, if the activity is low, the RMC decreases. + * The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly +becomes too large for the majority of users, and activity drops. -The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid price manipulations by malicious actors. -Note that blocks from issuers with negative BIC balances are excluded with respect to the RMC calculation, but they do make part of the slot commitment. -To limit fluctuations in the RMC, it is proposed to update its value every MCA slot at least. +The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid +price manipulations by malicious actors. Note that blocks from issuers with negative BIC balances are excluded with +respect to the RMC calculation, but they do make part of the slot commitment. To limit fluctuations in the RMC, +it is proposed to update its value every MCA slot at least. ## Mana decay -Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. To guarantee non-gameability (e.g., splitting accounts or other behaviours that are not helpful for the system well-functioning cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs to be applied to all forms of Mana: - -- newly generated Mana ([Potential Mana](#potential-mana)); -- Mana stored in UTXOs ([Stored Mana](#stored-mana)); -- Mana bound to accounts for block issuance ([Block Issuance Credit](#block-issuance-credit)); -- Mana rewarded for staking and delegation ([Mana rewards](#mana-rewards)). - -As the form in which the decay factor will be applied might differ between the Mana types, it is essential to point out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. - -Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every`2^(slotsPerEpochExponent)` slots, the epoch changes, meaning that every set of consecutive `2^(slotsPerEpochExponent)` slots will be in the same epoch. We set `slotsPerEpochExponent = 13`. - -The decay parameter `β` (together with the Mana generation parameter) was set so the maximum theoretical Mana in the system is `2^manaBits - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses `manaBits<64` bits (in the case of BIC, it uses at most `manaBits+1` bits, `manaBits` for the value and one for the sign). Notice that this value of `2^manaBits - 1` will almost certainly never be achieved, since for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values way smaller than `2^manaBits - 1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. - +Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana +generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. +To guarantee non-gameability (e.g., splitting accounts or other behaviors that are not helpful for the system +well-functioning cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs +to be applied to all forms of Mana: + * newly generated Mana ([Potential Mana](#potential-mana)); + * Mana stored in UTXOs ([Stored Mana](#stored-mana)); + * Mana bound to accounts for block issuance ([Block Issuance Credit](#block-issuance-credit)); + * Mana rewarded for staking and delegation ([Mana rewards](#mana-rewards)). + +As the form in which the decay factor will be applied might differ among the Mana types, it is essential to point +out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper +provides the specific formula for the decay function in Appendix A. + +Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of +storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In +any of those cases, the node must calculate the decay based on epoch indices, not local times. Every +`2^slotsPerEpochExponent` slots, the epoch changes, meaning that every set of consecutive `2^slotsPerEpochExponent` +slots will be in the same epoch. We set `slotsPerEpochExponent = 13`. + +The decay parameter `β` (together with the Mana generation parameter) was set so the maximum theoretical Mana in +the system is `2^manaBits - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses +`manaBits < 64` bits (in the case of BIC, it uses at most `manaBits + 1` bits, `manaBits` for the value and one +for the sign). Note that this value of `2^manaBits - 1` will almost certainly never be achieved since for the Mana +supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values +way smaller than `2^manaBits - 1`, however, we must count on what would be an unreasonably large value in practice +to avoid overflowing of the variables, even if with a really small probability. ## Mana and fixed point arithmetics - -Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding behavior in different architectures. The results of the operations involving floating point variables might differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, differences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviors in the system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. - -We introduce in the last section of this TIP a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the lookup Table introduced is an integer approximation of `2^(decayFactorsExponent) * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, for different values of `n`. We set `decayFactorsExponent = 32`, `epochDuration = 10*2^(slotsPerEpochExponent) = 10*2^13` seconds (which means that the duration of an epoch in years is around `0.002597666159`), and `β = 1/3` per year. - +Floating point operations might lead to inconsistencies among results in different nodes due to the different +rounding behavior in different architectures. The results of the operations involving floating point variables might +differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion +control module, for example); however, differences that would be considered negligible by those modules can be +fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviors in the +system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) +must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards +calculations have to be done with fixed point arithmetics. + +In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly +other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. +Specifically, the lookup table introduced is an integer approximation of +`2^decayFactorsExponent * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, +for different values of `n`. We set `decayFactorsExponent = 32`, +`epochDuration = 10 * 2^slotsPerEpochExponent = 10 * 2^13` seconds (which means that the duration of an epoch in +years is around `0.002597666159`), and `β = 1/3` per year. ### How to use the lookup table +==TODO: decide to max epoch in the table, if it's 365 or if we are adding values per year in the end== -==TO DO: decide to max epoch in the table, if it's 365 or if we are adding values per year in the end== +In this section, we define a function `decay(value, n)`, that decays an amount on Mana `value` by the factor +relative to `n` epochs. Note that the table defined above only gives the values of `lookupTable(n)` for some i +values of `n` up to `maxDecayFactor = 365`. To calculate `decay(value, n)` for larger values of `n`, we combine +values defined in the lookup table for other numbers smaller than `365`, using an algorithm that will be defined +below. First, we define three auxiliary functions: -In this section we define a function `decay(value, n)`, that decays an amount on Mana `value` by the factor relative to `n` epochs. Notice that the table defined above only gives the values of `lookupTable(n)` for some values of `n` up to `maxDecayFactor = 365`. To calculate `decay(value, n)` for larger values of `n`, we combine values defined in the lookup table for other numbers smaller than 365, using an algorithm that will be defined below. First, we define three auxiliary functions: - -``` +```go // Returns the upper n bits of a uint64 value func upperBits(value, n){ value = value >> n From 81b103f557ae396c997bb3a1d5e59b21c444803f Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Mon, 31 Jul 2023 11:33:56 +0200 Subject: [PATCH 048/157] Fix format, typos until Stored Mana sec --- tips/TIP-0039/tip-0039.md | 193 ++++++++++++++++++++++---------------- 1 file changed, 114 insertions(+), 79 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 3beabfa9a..6f1fd0014 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -174,18 +174,18 @@ func upperBits(value, n){ } ``` -``` +```go // Returns the upper n bits of a uint64 value func lowerBits(value, n){ - value = value << (64-n) - value = value >> (64-n) + value = value << (64 - n) + value = value >> (64 - n) return value } ``` -``` -// Returns the result of the multiplication ((valueHi<<32+valueLo)*multFactor)>>shiftFactor -// (where multFactor is a uint32, valueHi and valueLo are uint64 smaller than 2^32, and 0<=shiftFactor<=32), +```go +// Returns the result of the multiplication ((valueHi << 32 + valueLo) * multFactor) >> shiftFactor +// (where multFactor is a uint32, valueHi and valueLo are uint64 smaller than 2^32, and 0 <= shiftFactor <= 32), // using only uint64 multiplication functions, without overflowing. The returned result is split in 2 factors: // valueHi and valueLo, one containing the upper 32 bits of the result and the other containing the lower 32 bits. func MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor) (uint64, uint64) { @@ -195,30 +195,31 @@ func MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor) (uint64, // the lower shiftFactor bits of the result are extracted and shifted left to form the remainder. // valueLo is multiplied by multFactor and right-shifted by shiftFactor bits. // the sum of these two values forms the new lower part (valueLo) of the result. - valueLo = lowerBits(valueHi,shiftFactor)<<(32-shiftFactor) + (valueLo*multFactor)>>shiftFactor + valueLo = lowerBits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor // the right-shifted valueHi and the upper 32 bits of valueLo form the new higher part (valueHi) of the result. - valueHi = (valueHi >> shiftFactor) + upperBits(valueLo,32) + valueHi = (valueHi >> shiftFactor) + upperBits(valueLo, 32) // the lower 32 bits of valueLo form the new lower part of the result. - valueLo = lowerBits(valueLo,32) + valueLo = lowerBits(valueLo, 32) // return the result as a fixed-point number composed of two 64-bit integers return valueHi, valueLo } ``` -With the functions above defined, we procceed to define the `decay` funtion, that takes as input a uint64 valuable `value`and decays it by the correct decay factor, relative to `n` epochs. +With the functions above defined, we proceed to define the `decay` function that takes as input a `uint64` +value `value` and decays it by the correct decay factor relative to `n` epochs. -``` +```go func decay(value, n) { if value == 0 or n == 0 { return value } // split the value into two uint64 variables to prevent overflowing - valueHi = upperBits(value,32) - valueLo = lowerBits(value,32) + valueHi = upperBits(value, 32) + valueLo = lowerBits(value, 32) // we keep applying the lookup table factors as long as n epochs are left remainingEpochs = n @@ -236,80 +237,112 @@ func decay(value, n) { } // combine both uint64 variables to get the actual value - return valueHi<<32 + valueLo + return valueHi << 32 + valueLo } ``` -Other implementations of the functions above are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and multiplications with integers might lead to different results when the order is altered. -Example: suppose one needs to calculate `1002*99/100*21/100`. Following the left-to-right order, this would result in `1002*99/100*21/100 = 99198/100*21/100 = 991*21/100 = 20811/100 = 208`. If someone did this operation in a different order, let's say `1002*21/100*99/100`, the result would be `1002*21/100*99/100 = 21042/100*99/100 = 210*99/100 = 20790/100 = 207`. - +Other implementations of the functions above are possible; however, one must be careful with the order of +operations, which must be done as defined above. Having a well-defined order is crucial since sequences of +divisions and multiplications with integers might lead to different results when the order is altered. +Example: suppose one needs to calculate `1002 * 99 / 100 *21 / 100`. Following the left-to-right order, this +would result in `1002 * 99 / 100 * 21 / 100 = 99198 / 100 * 21 / 100 = 991 * 21 / 100 = 20811 / 100 = 208`. +If someone did this operation in a different order, let's say `1002 * 21 / 100 * 99 / 100`, the result would be +`1002 * 21 / 100 * 99 / 100 = 21042 / 100 * 99 / 100 = 210 * 99 / 100 = 20790 / 100 = 207`. ## Potential Mana -==TO DO : check if storage deposit ctually generate mana== +==TODO : check if storage deposit ctually generate mana== -*Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. -Every IOTA token, whether storage deposit or not, generates potential Mana. -The view on the potential Mana value can be deterministically derived from the UTXO ledger, -based on the UTXO IOTA token value and the time it was created in the UTXO metadata (we consider the creation time as the slot index of the transaction). +*Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token, whether +storage deposit or not, generates potential Mana. The view on the potential Mana value can be deterministically +derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created in the UTXO metadata +(we consider the creation time as the slot index of the transaction). ### Rationale behind the Potential Mana formulas - -We model the potential Mana generated by an output holding `S` IOTA tokens as the combination of a fixed generation per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time an epochends, where `Δ` is the epoch duration. +We model the potential Mana generated by an output holding `S` IOTA tokens as the combination of a fixed generation +per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time an epoch ends, where `Δ` i +is the epoch duration. ![](https://hackmd.io/_uploads/Bkzz3PiD2.png) -FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW +==TODO: FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW== -Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n = j - i` and for the sake of the explanation, assume `n > 1`. All the Mana generated in epoch `i` "crosses" `n` decay boundaries, thus, it must be decayed `n` times. The Mana generated in epoch `i + 1` "crosses" `n - 1` decay boundaries, so it must be decayed `n - 1` times, and so on, until the Mana generated in epoch `j`, which is not decayed at all. Adding these values, we find the following formulas (here `d` is the number of slots in a epoch): +Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n = j - i`, and for +the sake of the explanation, assume `n > 1`. All the Mana generated in epoch `i` "crosses" `n` decay boundaries; +thus, it must be decayed `n` times. The Mana generated in epoch `i + 1` "crosses" `n - 1` decay boundaries, so it +must be decayed `n - 1` times, and so on, until the Mana generated in epoch `j`, which is not decayed at all. +Adding these values, we find the following formulas (where `d` is the number of slots in an epoch): -`Potential Mana = γ * S * [d1 * exp(-β * Δ * n) + d * exp(-β * Δ * (n - 1)) + d * exp(-β * Δ * (n - 2)) + ... + d * exp(-β * Δ) + d2] = -γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = -γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))]`, where the summation is over `i = 1, ..., n - 1`. +`Potential Mana = γ * S * [d1 * exp(-β * Δ * n) + d * exp(-β * Δ * (n - 1)) + d * exp(-β * Δ * (n - 2)) + ... + +d * exp(-β * Δ) + d2] = γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = +γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))]`, +where the summation is over `i = 1, ..., n - 1`. -Analogously, if `n ≤ 1`, we find the following results (here `δ` is the difference between the creation and consumption slots): -- If `n = 1`: `Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2`. -- If `n = 0`: `Potential Mana = γ * S * δ`. +Analogously, if `n ≤ 1`, we find the following results (here `δ` is the difference between the creation and +consumption slots): + * If `n = 1`: `Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2`. + * If `n = 0`: `Potential Mana = γ * S * δ`. ### Potential Mana formulas with fixed point arithmetics - -The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated `2^decayFactorsExponent * exp(-β * Δ * i)` by `lookupTable(i)`, where `decayFactorsExponent` is the precision of the Lookup table used: - -If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form `c = decayFactorEpochsSum*2^(-decayFactorEpochsSumExponent)`. Given the values defined in the last section, we set `decayFactorEpochsSum=` and `decayFactorEpochsSumExponent=`. Then, `Potential_Mana = aux + aux1 + aux2`, where: -- `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; -- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-decayFactorsExponent) `; -- `aux2 = - c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n-1)+1) * 2^(-decayFactorsExponent)`; +The formulas found in the last section are the exact formulas for the model proposed. However, we must not use +floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the +formula for `n > 1`, noticing that we already approximated `2^decayFactorsExponent * exp(-β * Δ * i)` by +`lookupTable(i)`, where `decayFactorsExponent` is the precision of the lookup table used. + +If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form +`c = decayFactorEpochsSum * 2^(-decayFactorEpochsSumExponent)`. Given the values defined in the last section, +we set `decayFactorEpochsSum = TODO` and `decayFactorEpochsSumExponent= TODO`. Then, +`Potential_Mana = aux + aux1 + aux2`, where: + * `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; + * `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-decayFactorsExponent) `; + * `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-decayFactorsExponent)`; and -- `slotPerEpoch = 2^slotsPerEpochExponent` is the number of slots in an epoch. Initially, we use `slotsPerEpochExponent = 13`. -- `d1 = slotAfterEpochi - creationSlot` -- `slotAfterEpochi` is the first slot of the epoch `i + 1` ; -- `d2 = consumptionSlot - firstSlotEpochJ` -- `firstSlotEpochJ` is the first slot of epoch `j` ; -- `generationPerSlot = generationRate * 2^(-generationRateExponent)` is the Mana generated by holding 1 IOTA for 1 slot. Initially, we use `generationRate = 1` and `generationRateExponent=80-manaBits`. This generation rate per slot guarantees that the maximum theoretical mana in the system uses the `manaBits` available bits; -- `manaBits = 63`. + * `slotPerEpoch = 2^slotsPerEpochExponent` is the number of slots in an epoch. Initially, we use +`slotsPerEpochExponent = 13`; + * `d1 = slotAfterEpochi - creationSlot`; + * `slotAfterEpochi` is the first slot of the epoch `i + 1`; + * `d2 = consumptionSlot - firstSlotEpochJ` + * `firstSlotEpochJ` is the first slot of epoch `j` ; + * `generationPerSlot = generationRate * 2^(-generationRateExponent)` is the Mana generated by holding 1 IOTA for +1 slot. Initially, we use `generationRate = 1` and `generationRateExponent = 80 - manaBits`. This generation rate +per slot guarantees that the maximum theoretical mana in the system uses the `manaBits` available bits; + * `manaBits = 63`. -Note that the term `aux2` has a factor `lookupTable(n-1)+1` instead of `lookupTable(n-1)` since the values in the lookup table are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing this, we avoid potential gameability scenarios, since all the terms added will be rounded by below in the formula. - -Rearranging the formuals above, we have that `Potential_Mana = potentialMana0 + potentialManan + potentialManan1`, where - -- `potentialMana0 = amount * d2 * generationRate * 2^(-generationRateExponent) + c * amount * generationRate * 2^(slotsPerEpochExponent-generationRateExponent)- c * amount * generationRate * 2^(slotsPerEpochExponent-decayFactorsExponent-generationRateExponent)` -- `potentialManan = amount * d1 * lookupTable(n) * generationRate * 2^(-decayFactorsExponent-generationRateExponent) ` -- `potentialManan1 = - c * amount * generationRate * lookupTable(n-1) * 2^(slotsPerEpochExponent-decayFactorsExponent-generationRateExponent)` - -Analogously, we find formulas for `n < 2:` -- If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * generationRate * 2^(-decayFactorsExponent-generationRateExponent) + amount * d2 * generationRate * 2^(-generationRateExponent)` -- If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * generationRate * 2^(-generationRateExponent)` - -In the next section, we introduce the defaut implementation for the formulas presented above. +Note that the term `aux2` has a factor `lookupTable(n - 1) + 1` instead of `lookupTable(n - 1)` since the values +in the lookup table are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing +this, we avoid potential gameability scenarios, since all the terms added will be rounded down in the formula. + +Rearranging the formulas above, we have that `Potential_Mana = potentialMana0 + potentialManan + potentialManan1`, +where + * `potentialMana0 = amount * d2 * generationRate * 2^(-generationRateExponent) + c * amount * generationRate * +2^(slotsPerEpochExponent - generationRateExponent) - c * amount * generationRate * +2^(slotsPerEpochExponent - decayFactorsExponent - generationRateExponent)`; + * `potentialManan = amount * d1 * lookupTable(n) * generationRate * 2^(-decayFactorsExponent-generationRateExponent)`; + * `potentialManan1 = -c * amount * generationRate * lookupTable(n - 1) * +2^(slotsPerEpochExponent - decayFactorsExponent - generationRateExponent)`. + +Analogously, we find formulas for `n < 2`: + * If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * generationRate * +2^(-decayFactorsExponent - generationRateExponent) + amount * d2 * generationRate * 2^(-generationRateExponent)`. + * If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * generationRate * +2^(-generationRateExponent)`. + +In the next section, we introduce the default implementation for the formulas presented above. ### Potential Mana Semantic Validation -- Potential Mana must and can only be consumed when the corresponding output is consumed. -- When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the accumulated potential Mana value. There are three options: - - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; + * Potential Mana must and can only be consumed when the corresponding output is consumed. + * When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the +accumulated potential Mana value. There are three options: + - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be +placed in the newly created output on the output side of the transaction; + - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance +Credit (BIC) should be specified in the `Allotment` field of the transaction; - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. -- The exact algorithm to calculate the Potential Mana generated by an output created at slot `creationSlot` (which has an epoch`creationEpoch`) and consumed at slot `consumptionSlot` (which has an epoch`consumptionEpoch`), holding `Amount` IOTA tokens, is given by (again, in the pseudocode below, `slotAfterCreationEpoch` is the first slot of the epoch after the creation epoch and `firstSlotConsumptionEpoch` is the first slot of the consumption epoch) the algorithms define below. - + * The exact algorithm to calculate the Potential Mana generated by an output created at slot `creationSlot` i +(which has an epoch `creationEpoch`) and consumed at slot `consumptionSlot` (which has an epoch `consumptionEpoch`), +holding `Amount` IOTA tokens, is given by (again, in the pseudocode below, `slotAfterCreationEpoch` is the first +slot of the epoch after the creation epoch and `firstSlotConsumptionEpoch` is the first slot of the consumption +epoch) the algorithms define below.
Lookup Table: Decays for Mana in decay index granularity scaled to 2^32
n Type
1 - uint16 4092 uint32 4291249941
2 - uint16 4088 uint32 4287535805
3 - uint16 4085 uint32 4283824883
4 - uint16 4081 uint32 4280117173
5 - uint16 4078 uint32 4276412671
6 - uint16 4074 uint32 4272711377
7 - uint16 4071 uint32 4269013285
8 - uint16 4067 uint32 4265318395
9 - uint16 4064 uint32 4261626702
10 - uint16 4060 uint32 4257938205
11 - uint16 4057 uint32 4254252900
12 - uint16 4053 uint32 4250570785
13 - uint16 4050 uint32 4246891856
14 - uint16 4046 uint32 4243216112
15 - uint16 4043 uint32 4239543550
16 - uint16 4039 uint32 4235874166
17 - uint16 4036 uint32 4232207957
18 - uint16 4032 uint32 4228544922
19 - uint16 4029 uint32 4224885058
20 - uint16 4025 uint32 4221228361
21 - uint16 4022 uint32 4217574829
22 - uint16 4018 uint32 4213924459
23 - uint16 4015 uint32 4210277249
24 - uint16 4011 uint32 4206633195
25 - uint16 4008 uint32 4202992295
26 - uint16 4004 uint32 4199354547
27 - uint16 4001 uint32 4195719947
28 - uint16 3997 uint32 4192088493
29 - uint16 3994 uint32 4188460182
30 - uint16 3990 uint32 4184835011
31 - uint16 3987 uint32 4181212978
32 - uint16 3984 uint32 4177594080
33 - uint16 3980 uint32 4173978314
34 - uint16 3977 uint32 4170365677
35 - uint16 3973 uint32 4166756168
36 - uint16 3970 uint32 4163149782
37 - uint16 3966 uint32 4159546518
38 - uint16 3963 uint32 4155946372
39 - uint16 3959 uint32 4152349343
40 - uint16 3956 uint32 4148755427
41 - uint16 3953 uint32 4145164621
42 - uint16 3949 uint32 4141576923
43 - uint16 3946 uint32 4137992331
44 - uint16 3942 uint32 4134410840
45 - uint16 3939 uint32 4130832450
46 - uint16 3936 uint32 4127257157
47 - uint16 3932 uint32 4123684959
48 - uint16 3929 uint32 4120115852
49 - uint16 3925 uint32 4116549834
50 - uint16 3922 uint32 4112986903
51 - uint16 3919 uint32 4109427055
52 - uint16 3915 uint32 4105870289
53 - uint16 3912 uint32 4102316601
54 - uint16 3908 uint32 4098765988
55 - uint16 3905 uint32 4095218449
56 - uint16 3902 uint32 4091673981
57 - uint16 3898 uint32 4088132580
58 - uint16 3895 uint32 4084594244
59 - uint16 3892 uint32 4081058971
60 - uint16 3888 uint32 4077526757
61 - uint16 3885 uint32 4073997601
62 - uint16 3881 uint32 4070471499
63 - uint16 3878 uint32 4066948449
64 - uint16 3875 uint32 4063428449
65 - uint16 3871 uint32 4059911495
66 - uint16 3868 uint32 4056397585
67 - uint16 3865 uint32 4052886716
68 - uint16 3861 uint32 4049378886
69 - uint16 3858 uint32 4045874092
70 - uint16 3855 uint32 4042372332
71 - uint16 3851 uint32 4038873602
72 - uint16 3848 uint32 4035377901
73 - uint16 3845 uint32 4031885225
74 - uint16 3841 uint32 4028395572
75 - uint16 3838 uint32 4024908939
76 - uint16 3835 uint32 4021425325
77 - uint16 3831 uint32 4017944725
78 - uint16 3828 uint32 4014467138
79 - uint16 3825 uint32 4010992560
80 - uint16 3821 uint32 4007520990
81 - uint16 3818 uint32 4004052425
82 - uint16 3815 uint32 4000586862
83 - uint16 3811 uint32 3997124298
84 - uint16 3808 uint32 3993664731
85 - uint16 3805 uint32 3990208159
86 - uint16 3802 uint32 3986754578
87 - uint16 3798 uint32 3983303986
88 - uint16 3795 uint32 3979856381
89 - uint16 3792 uint32 3976411760
90 - uint16 3788 uint32 3972970120
91 - uint16 3785 uint32 3969531459
92 - uint16 3782 uint32 3966095774
93 - uint16 3779 uint32 3962663063
94 - uint16 3775 uint32 3959233323
95 - uint16 3772 uint32 3955806551
96 - uint16 3769 uint32 3952382745
97 - uint16 3766 uint32 3948961903
98 - uint16 3762 uint32 3945544021
99 - uint16 3759 uint32 3942129098
100 - uint16 3756 uint32 3938717130
101 - uint16 3753 uint32 3935308116
102 - uint16 3749 uint32 3931902052
103 - uint16 3746 uint32 3928498936
104 - uint16 3743 uint32 3925098765
105 - uint16 3740 uint32 3921701537
106 - uint16 3736 uint32 3918307250
107 - uint16 3733 uint32 3914915900
108 - uint16 3730 uint32 3911527486
109 - uint16 3727 uint32 3908142004
110 - uint16 3723 uint32 3904759453
111 - uint16 3720 uint32 3901379829
112 - uint16 3717 uint32 3898003131
113 - uint16 3714 uint32 3894629355
114 - uint16 3710 uint32 3891258499
115 - uint16 3707 uint32 3887890560
116 - uint16 3704 uint32 3884525537
117 - uint16 3701 uint32 3881163426
118 - uint16 3698 uint32 3877804224
119 - uint16 3694 uint32 3874447931
120 - uint16 3691 uint32 3871094542
121 - uint16 3688 uint32 3867744056
122 - uint16 3685 uint32 3864396469
123 - uint16 3682 uint32 3861051780
124 - uint16 3678 uint32 3857709986
125 - uint16 3675 uint32 3854371084
126 - uint16 3672 uint32 3851035072
127 - uint16 3669 uint32 3847701948
128 - uint16 3666 uint32 3844371708
129 - uint16 3663 uint32 3841044351
130 - uint16 3659 uint32 3837719873
131 - uint16 3656 uint32 3834398273
132 - uint16 3653 uint32 3831079548
133 - uint16 3650 uint32 3827763695
134 - uint16 3647 uint32 3824450713
135 - uint16 3644 uint32 3821140597
136 - uint16 3640 uint32 3817833347
137 - uint16 3637 uint32 3814528959
138 - uint16 3634 uint32 3811227431
139 - uint16 3631 uint32 3807928760
140 - uint16 3628 uint32 3804632945
141 - uint16 3625 uint32 3801339982
142 - uint16 3622 uint32 3798049869
143 - uint16 3618 uint32 3794762604
144 - uint16 3615 uint32 3791478184
145 - uint16 3612 uint32 3788196607
146 - uint16 3609 uint32 3784917870
147 - uint16 3606 uint32 3781641970
148 - uint16 3603 uint32 3778368907
149 - uint16 3600 uint32 3775098676
150 - uint16 3597 uint32 3771831275
151 - uint16 3593 uint32 3768566702
152 - uint16 3590 uint32 3765304955
153 - uint16 3587 uint32 3762046031
154 - uint16 3584 uint32 3758789928
155 - uint16 3581 uint32 3755536643
156 - uint16 3578 uint32 3752286174
157 - uint16 3575 uint32 3749038518
158 - uint16 3572 uint32 3745793673
159 - uint16 3569 uint32 3742551636
160 - uint16 3566 uint32 3739312405
161 - uint16 3562 uint32 3736075978
162 - uint16 3559 uint32 3732842352
163 - uint16 3556 uint32 3729611525
164 - uint16 3553 uint32 3726383494
165 - uint16 3550 uint32 3723158258
166 - uint16 3547 uint32 3719935812
167 - uint16 3544 uint32 3716716156
168 - uint16 3541 uint32 3713499286
169 - uint16 3538 uint32 3710285201
170 - uint16 3535 uint32 3707073897
171 - uint16 3532 uint32 3703865373
172 - uint16 3529 uint32 3700659626
173 - uint16 3526 uint32 3697456653
174 - uint16 3523 uint32 3694256453
175 - uint16 3520 uint32 3691059023
176 - uint16 3517 uint32 3687864360
177 - uint16 3513 uint32 3684672462
178 - uint16 3510 uint32 3681483326
179 - uint16 3507 uint32 3678296951
180 - uint16 3504 uint32 3675113334
181 - uint16 3501 uint32 3671932472
182 - uint16 3498 uint32 3668754363
183 - uint16 3495 uint32 3665579005
184 - uint16 3492 uint32 3662406395
185 - uint16 3489 uint32 3659236531
186 - uint16 3486 uint32 3656069411
187 - uint16 3483 uint32 3652905032
188 - uint16 3480 uint32 3649743392
189 - uint16 3477 uint32 3646584488
190 - uint16 3474 uint32 3643428318
191 - uint16 3471 uint32 3640274880
192 - uint16 3468 uint32 3637124172
193 - uint16 3465 uint32 3633976190
194 - uint16 3462 uint32 3630830933
195 - uint16 3459 uint32 3627688398
196 - uint16 3456 uint32 3624548583
197 - uint16 3453 uint32 3621411486
198 - uint16 3450 uint32 3618277104
199 - uint16 3447 uint32 3615145434
200 - uint16 3444 uint32 3612016476
201 - uint16 3441 uint32 3608890225
202 - uint16 3438 uint32 3605766680
203 - uint16 3435 uint32 3602645839
204 - uint16 3432 uint32 3599527699
205 - uint16 3429 uint32 3596412257
206 - uint16 3426 uint32 3593299512
207 - uint16 3423 uint32 3590189461
208 - uint16 3420 uint32 3587082102
209 - uint16 3417 uint32 3583977433
210 - uint16 3414 uint32 3580875450
211 - uint16 3412 uint32 3577776153
212 - uint16 3409 uint32 3574679537
213 - uint16 3406 uint32 3571585602
214 - uint16 3403 uint32 3568494345
215 - uint16 3400 uint32 3565405764
216 - uint16 3397 uint32 3562319855
217 - uint16 3394 uint32 3559236618
218 - uint16 3391 uint32 3556156049
219 - uint16 3388 uint32 3553078146
220 - uint16 3385 uint32 3550002907
221 - uint16 3382 uint32 3546930330
222 - uint16 3379 uint32 3543860413
223 - uint16 3376 uint32 3540793152
224 - uint16 3373 uint32 3537728546
225 - uint16 3370 uint32 3534666593
226 - uint16 3368 uint32 3531607290
227 - uint16 3365 uint32 3528550634
228 - uint16 3362 uint32 3525496624
229 - uint16 3359 uint32 3522445258
230 - uint16 3356 uint32 3519396533
231 - uint16 3353 uint32 3516350446
232 - uint16 3350 uint32 3513306995
233 - uint16 3347 uint32 3510266179
234 - uint16 3344 uint32 3507227995
235 - uint16 3341 uint32 3504192440
236 - uint16 3338 uint32 3501159513
237 - uint16 3336 uint32 3498129210
238 - uint16 3333 uint32 3495101531
239 - uint16 3330 uint32 3492076472
240 - uint16 3327 uint32 3489054031
241 - uint16 3324 uint32 3486034206
242 - uint16 3321 uint32 3483016995
243 - uint16 3318 uint32 3480002395
244 - uint16 3315 uint32 3476990404
245 - uint16 3313 uint32 3473981020
246 - uint16 3310 uint32 3470974241
247 - uint16 3307 uint32 3467970065
248 - uint16 3304 uint32 3464968488
249 - uint16 3301 uint32 3461969510
250 - uint16 3298 uint32 3458973127
251 - uint16 3295 uint32 3455979337
252 - uint16 3293 uint32 3452988139
253 - uint16 3290 uint32 3449999530
254 - uint16 3287 uint32 3447013507
255 - uint16 3284 uint32 3444030069
256 - uint16 3281 uint32 3441049213
257 - uint16 3278 uint32 3438070937
258 - uint16 3275 uint32 3435095238
259 - uint16 3273 uint32 3432122115
260 - uint16 3270 uint32 3429151566
261 - uint16 3267 uint32 3426183587
262 - uint16 3264 uint32 3423218178
263 - uint16 3261 uint32 3420255335
264 - uint16 3258 uint32 3417295056
265 - uint16 3256 uint32 3414337339
266 - uint16 3253 uint32 3411382183
267 - uint16 3250 uint32 3408429584
268 - uint16 3247 uint32 3405479541
269 - uint16 3244 uint32 3402532051
270 - uint16 3242 uint32 3399587112
271 - uint16 3239 uint32 3396644722
272 - uint16 3236 uint32 3393704878
273 - uint16 3233 uint32 3390767579
274 - uint16 3230 uint32 3387832823
275 - uint16 3228 uint32 3384900606
276 - uint16 3225 uint32 3381970927
277 - uint16 3222 uint32 3379043784
278 - uint16 3219 uint32 3376119175
279 - uint16 3216 uint32 3373197097
280 - uint16 3214 uint32 3370277548
281 - uint16 3211 uint32 3367360525
282 - uint16 3208 uint32 3364446028
283 - uint16 3205 uint32 3361534053
284 - uint16 3203 uint32 3358624598
285 - uint16 3200 uint32 3355717662
286 - uint16 3197 uint32 3352813241
287 - uint16 3194 uint32 3349911335
288 - uint16 3191 uint32 3347011940
289 - uint16 3189 uint32 3344115054
290 - uint16 3186 uint32 3341220676
291 - uint16 3183 uint32 3338328803
292 - uint16 3180 uint32 3335439433
293 - uint16 3178 uint32 3332552563
294 - uint16 3175 uint32 3329668193
295 - uint16 3172 uint32 3326786318
296 - uint16 3169 uint32 3323906939
297 - uint16 3167 uint32 3321030051
298 - uint16 3164 uint32 3318155653
299 - uint16 3161 uint32 3315283743
300 - uint16 3158 uint32 3312414319
301 - uint16 3156 uint32 3309547378
302 - uint16 3153 uint32 3306682918
303 - uint16 3150 uint32 3303820938
304 - uint16 3148 uint32 3300961435
305 - uint16 3145 uint32 3298104407
306 - uint16 3142 uint32 3295249852
307 - uint16 3139 uint32 3292397767
308 - uint16 3137 uint32 3289548151
309 - uint16 3134 uint32 3286701001
310 - uint16 3131 uint32 3283856315
311 - uint16 3129 uint32 3281014092
312 - uint16 3126 uint32 3278174328
313 - uint16 3123 uint32 3275337023
314 - uint16 3120 uint32 3272502173
315 - uint16 3118 uint32 3269669777
316 - uint16 3115 uint32 3266839832
317 - uint16 3112 uint32 3264012336
318 - uint16 3110 uint32 3261187288
319 - uint16 3107 uint32 3258364685
320 - uint16 3104 uint32 3255544525
321 - uint16 3102 uint32 3252726806
322 - uint16 3099 uint32 3249911526
323 - uint16 3096 uint32 3247098682
324 - uint16 3093 uint32 3244288273
325 - uint16 3091 uint32 3241480296
326 - uint16 3088 uint32 3238674749
327 - uint16 3085 uint32 3235871631
328 - uint16 3083 uint32 3233070939
329 - uint16 3080 uint32 3230272671
330 - uint16 3077 uint32 3227476825
331 - uint16 3075 uint32 3224683399
332 - uint16 3072 uint32 3221892391
333 - uint16 3069 uint32 3219103798
334 - uint16 3067 uint32 3216317619
335 - uint16 3064 uint32 3213533851
336 - uint16 3062 uint32 3210752492
337 - uint16 3059 uint32 3207973541
338 - uint16 3056 uint32 3205196995
339 - uint16 3054 uint32 3202422853
340 - uint16 3051 uint32 3199651111
341 - uint16 3048 uint32 3196881768
342 - uint16 3046 uint32 3194114823
343 - uint16 3043 uint32 3191350272
344 - uint16 3040 uint32 3188588114
345 - uint16 3038 uint32 3185828346
346 - uint16 3035 uint32 3183070967
347 - uint16 3032 uint32 3180315975
348 - uint16 3030 uint32 3177563367
349 - uint16 3027 uint32 3174813142
350 - uint16 3025 uint32 3172065297
351 - uint16 3022 uint32 3169319830
352 - uint16 3019 uint32 3166576739
353 - uint16 3017 uint32 3163836023
354 - uint16 3014 uint32 3161097679
355 - uint16 3012 uint32 3158361705
356 - uint16 3009 uint32 3155628099
357 - uint16 3006 uint32 3152896859
358 - uint16 3004 uint32 3150167982
359 - uint16 3001 uint32 3147441468
360 - uint16 2999 uint32 3144717314
361 - uint16 2996 uint32 3141995517
362 - uint16 2993 uint32 3139276076
363 - uint16 2991 uint32 3136558989
364 - uint16 2988 uint32 3133844253
365 - uint16 2986 uint32 3131131867
@@ -341,45 +374,47 @@ In the next section, we introduce the defaut implementation for the formulas pre
-==To do: talk about the missing remainder== - +==TODO: talk about the missing remainder== -We begin by defining an auxiliary function that (intuitively) generates Mana without applying any type of decay (note that we use some of the functions and constants defined in the last sections): +We begin by defining an auxiliary function that (intuitively) generates Mana without applying any type of decay +(note that we use some of the functions and constants defined in the last sections): -``` +```go // generateMana calculates the generated mana from holding `value` tokens for `m` slots, without applying any decay. func generateMana(value, m) { if m == 0 or generationRate == 0 { return 0 } - return MultiplicationAndShift(value, m*generationRate, generationRateExponent) + return MultiplicationAndShift(value, m * generationRate, generationRateExponent) } -```` +``` -Now we define the function that actually calculates the Potential Mana using the formulas defined in the last section (including the decays). Let `n=consumptionSlot-creationSlot`, `d1=slotAfterCreationEpoch-creationSlot`, and `d2=consumptionSlot-firstSlotConsumptionEpoch`. Then, we have: +Now we define the function that actually calculates the Potential Mana using the formulas defined in the last i +section (including the decays). Let `n = consumptionSlot - creationSlot`, `d1 = slotAfterCreationEpoch - creationSlot`, +and `d2 = consumptionSlot - firstSlotConsumptionEpoch`. Then, we have: -``` +```go // PotentialManaWithDecay calculates the generated potential mana and applies the decay to the result. func PotentialManaWithDecay(value, n, d1, d2) { if n == 0: - return generateMana(value, d1+d2-2^slotsPerEpochExponent) + return generateMana(value, d1 + d2 - 2^slotsPerEpochExponent) else if n == 1: return decay(generateMana(value, d1), 1) + generateMana(value, d2) else: - aux = MultiplicationAndShift(value*generationRate, decayFactorEpochsSum, decayFactorEpochsSumExponent+generationRateExponent-slotsPerEpochExponent) + aux = MultiplicationAndShift(value * generationRate, decayFactorEpochsSum, decayFactorEpochsSumExponent + +generationRateExponent - slotsPerEpochExponent) potentialMana_n := decay(generateMana(value, d1), n) - potentialMana_n_1 := decay(aux, n-1) - potentialMana_0 := generateMana(value, d2) + aux - aux>>decayFactorsExponent + potentialMana_n_1 := decay(aux, n - 1) + potentialMana_0 := generateMana(value, d2) + aux - aux >> decayFactorsExponent return potentialMana_n - potentialMana_n_1 + potentialMana_0 } ``` -==to do: talk with max about the generationRate in aux and generateMana== +==TODO: talk with max about the generationRate in aux and generateMana== ## Stored Mana - *Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA tokens) of Mana that can be transferred within certain rules between different users, which allows for Mana market development. All output types except Foundry Outputs can hold stored Mana in the *Mana Amount* field. From 5471a229f84815daddc579f4564556dc46ffe65a Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Mon, 31 Jul 2023 11:59:46 +0200 Subject: [PATCH 049/157] Update tips/TIP-0039/tip-0039.md Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 6f1fd0014..1a4c101ab 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -57,7 +57,7 @@ fully use all the Mana functionalities, the user is required to have an account, # Building Blocks ## Mana design -Mana is a core element of the IOTA inactivation scheme. It is a resource that can be obtained through: +Mana is a core element of the IOTA incentive scheme. It is a resource that can be obtained through: * generating by holding IOTA tokens; * as a reward for staking IOTA tokens; * as a reward for delegating IOTA tokens; From 3921be1d17e5bdb767b4246a5584e6a76db2b8e3 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Mon, 31 Jul 2023 12:13:34 +0200 Subject: [PATCH 050/157] Fix format, typos --- tips/TIP-0039/tip-0039.md | 193 ++++++++++++++++++++++---------------- 1 file changed, 114 insertions(+), 79 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 6f1fd0014..a126b963f 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -37,11 +37,13 @@ requires: TIP-42 - [Copyright](#copyright) # Summary + This document defines the Mana-related concepts and the Mana dynamics in the IOTA 2.0 protocol. The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana,** as well as the **Block Issuance Credit (BIC)** that Mana can be allotted to. # Motivation + Mana is a resource used to determine the allowed throughput of a user and as a payment form for block issuance in the Mana burn mechanism. Mana can be obtained by helpful and profitable actions for the network, like token holding or engagement in securing the network. Additionally, owning Mana is necessary to use the network by issuing @@ -57,6 +59,7 @@ fully use all the Mana functionalities, the user is required to have an account, # Building Blocks ## Mana design + Mana is a core element of the IOTA inactivation scheme. It is a resource that can be obtained through: * generating by holding IOTA tokens; * as a reward for staking IOTA tokens; @@ -87,6 +90,7 @@ tokens. The Mana rewarded from staking and validation must be claimed and stored The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. ## Mana burn + According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a certain amount of Mana dictated by the size of the block and the Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Therefore, in order to prevent being locked out of their @@ -94,6 +98,7 @@ account, the block issuer must ensure that sufficient Mana is also allotted to t balance remains non-negative. ### Reference Mana Cost + *Reference Mana Cost (RMC)* is used to decide how much Mana should be burned from BIC by each block in that slot. RMC is computed according to an algorithm based on recent traffic activity: the algorithm counts the number of blocks in slots that are *Maximum Committable Age (MCA)* slots in the past so that all nodes agree on that value of @@ -111,6 +116,7 @@ respect to the RMC calculation, but they do make part of the slot commitment. To it is proposed to update its value every MCA slot at least. ## Mana decay + Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. To guarantee non-gameability (e.g., splitting accounts or other behaviors that are not helpful for the system @@ -140,6 +146,7 @@ way smaller than `2^manaBits - 1`, however, we must count on what would be an un to avoid overflowing of the variables, even if with a really small probability. ## Mana and fixed point arithmetics + Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding behavior in different architectures. The results of the operations involving floating point variables might differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion @@ -158,6 +165,7 @@ for different values of `n`. We set `decayFactorsExponent = 32`, years is around `0.002597666159`), and `β = 1/3` per year. ### How to use the lookup table + ==TODO: decide to max epoch in the table, if it's 365 or if we are adding values per year in the end== In this section, we define a function `decay(value, n)`, that decays an amount on Mana `value` by the factor @@ -250,6 +258,7 @@ If someone did this operation in a different order, let's say `1002 * 21 / 100 * `1002 * 21 / 100 * 99 / 100 = 21042 / 100 * 99 / 100 = 210 * 99 / 100 = 20790 / 100 = 207`. ## Potential Mana + ==TODO : check if storage deposit ctually generate mana== *Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token, whether @@ -258,6 +267,7 @@ derived from the UTXO ledger, based on the UTXO IOTA token value and the time it (we consider the creation time as the slot index of the transaction). ### Rationale behind the Potential Mana formulas + We model the potential Mana generated by an output holding `S` IOTA tokens as the combination of a fixed generation per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time an epoch ends, where `Δ` i is the epoch duration. @@ -283,6 +293,7 @@ consumption slots): * If `n = 0`: `Potential Mana = γ * S * δ`. ### Potential Mana formulas with fixed point arithmetics + The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated `2^decayFactorsExponent * exp(-β * Δ * i)` by @@ -330,6 +341,7 @@ Analogously, we find formulas for `n < 2`: In the next section, we introduce the default implementation for the formulas presented above. ### Potential Mana Semantic Validation + * Potential Mana must and can only be consumed when the corresponding output is consumed. * When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the accumulated potential Mana value. There are three options: @@ -415,21 +427,29 @@ generationRateExponent - slotsPerEpochExponent) ==TODO: talk with max about the generationRate in aux and generateMana== ## Stored Mana -*Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA tokens) of Mana that can be transferred within certain rules between different users, which allows for Mana market development. -All output types except Foundry Outputs can hold stored Mana in the *Mana Amount* field. -This field represents the amount of stored Mana at the output's creation time until the time when the output is consumed without decay being applied to it. +*Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA +tokens) of Mana that can be transferred within certain rules between different users, which allows for Mana +market development. + +All output types, except Foundry Outputs, can hold stored Mana in the *Mana Amount* field. This field represents the +amount of stored Mana at the output's creation time until the time when the output is consumed without decay +being applied to it. ### Stored Mana Semantic Validation -- Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. -- Stored Mana must be soulbound to an account. -- Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be spent within a block. It must be allotted to an account's BIC in order to pay for Mana burned by blocks. -- *Mana Sales Outputs* must be used for transferring stored or potential Mana freely from one account to another. -- It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. -- The decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. -- To calculate the decay of stored Mana, the creation time of each output with stored Mana must be contained in transactions. -- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: - - Let `manaAmount`, `consumptionSlot`, and `creationSlot`, be + + * Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. + * Stored Mana must be soulbound to an account. + * Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be spent within a block. It must +be allotted to an account's BIC in order to pay for Mana burned by blocks. + * *Mana Sales Outputs* must be used for transferring stored or potential Mana freely from one account to another. + * It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from +those tokens. + * The decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. + * To calculate the decay of stored Mana, the creation time of each output with stored Mana must be contained in +transactions. + * The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: + - Let `manaAmount`, `consumptionSlot`, and `creationSlot`, be @@ -460,91 +480,109 @@ This field represents the amount of stored Mana at the output's creation time un
- The algorithm to decay the stored Mana is as follows - - +The algorithm to decay the stored Mana is as follows: -``` +```go creationEpoch = epoch(creationSlot) consumptionEpoch = epoch(consumptionSlot) if creationEpoch == consumptionEpoch: newManaAmount = manaAmount else: - newManaAmount = decay(manaAmount,consumptionEpoch-creationEpoch) - + newManaAmount = decay(manaAmount, consumptionEpoch - creationEpoch) ``` ## Block Issuance Credit -*Block Issuance Credit (BIC)* Mana is used for congestion control, i.e., to pay for blocks to be scheduled and gossiped around the network and seen by everyone. -Congestion control manages which blocks should be gossiped to neighbors based on Mana burned from the block issuance credits by the block. -It is important to distinguish between **blocks** and **transactions**: -congestion control only deals with blocks, which are the containers that carry transactions around the network. It does not care about the transactions inside the blocks. +*Block Issuance Credit (BIC)* Mana is used for congestion control, i.e., to pay for blocks to be scheduled and +gossiped around the network and seen by everyone. Congestion control manages which blocks should be gossiped to +neighbors based on Mana burned from the block issuance credits by the block. It is important to distinguish +between **blocks** and **transactions**: congestion control only deals with blocks, which are the containers that carry transactions around the network. It does not care about the transactions inside the blocks. + +The example below shows a ledger with a conflicting branch (perhaps due to a double spend), so only one branch +(either the set of red or the set of green transactions) can ultimately modify the ledger (UTXOs consumed), not both. +However, all these blocks must be gossiped, whether they contain red or green transactions. Thus, they must pay for +the BIC used to get through schedulers regardless of whether the transaction within modifies the ledger. This is +why Mana cannot be burned from BIC by a transaction; it can only be burned by a block. -The example below shows a ledger with a conflicting branch (perhaps due to a double spend), so only one branch (either the set of red or the set of green transactions) -can ultimately modify the ledger (UTXOs consumed), not both. However, all these blocks must be gossiped, whether they contain red or green transactions. -Thus, they must pay for the BIC used to get through schedulers regardless of whether the transaction within modifies the ledger. -This is why Mana cannot be burned from BIC by a transaction, it can only be burned by a block. ![](./img/gFLB1Ms.png) ### Block Issuance Credit Semantic Validation -- Block issuance credits must be stored on a per-account basis. -- Accounts must be represented by _Account Outputs_ on the UTXO ledger. The cost of permanently storing any outputs (until destruction) in the ledger is covered by the _storage deposit_. -Because of that, the number of accounts is capped at a number proportional to the max supply of tokens, contrary to the number of plain addresses. -Because BIC must be tracked in slot commitments, keeping the number of entries (even though the user can create multiple accounts) in that data structure as small as possible is desirable. -Using account IDs for that purpose is thus a good fit. -- It is not possible to store BIC without an Account Output because Mana burned by blocks must also be deducted from BIC, and the block cannot modify the Account Output. -Consequently, the ledger state is not bloated by having to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that requires a storage deposit -in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the block issuance credits. -- A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. + + * Block issuance credits must be stored on a per-account basis. + * Accounts must be represented by _Account Outputs_ on the UTXO ledger. The cost of permanently storing any outputs +(until destruction) in the ledger is covered by the _storage deposit_. Because of that, the number of accounts is +capped at a number proportional to the max supply of tokens, contrary to the number of plain addresses. Because +BIC must be tracked in slot commitments, keeping the number of entries (even though the user can create multiple +accounts) in that data structure as small as possible is desirable. Using account IDs for that purpose is thus a +good fit. + * It is not possible to store BIC without an Account Output because Mana burned by blocks must also be deducted +from BIC, and the block cannot modify the Account Output. Consequently, the ledger state is not bloated by having +to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that +requires a storage deposit in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also +indirectly prevents dust from accumulating in tracking the block issuance credits. + * A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. - The end time of an epoch is used for the decay calculations. - Definition of slots based on the time of the genesis slot and slot duration. - A commitment mechanism per slot is needed to ensure the unified perception of the BIC in the longer run. -- The global agreement on the BIC balances among all the nodes is required. - - It can be achieved by including the BIC vector in the slot commitments. This guarantees that all nodes have the same perception of the BIC balances from a certain point in time. -- If a block is orphaned, the block will not be included in a commitment, and hence, the balance of BIC of the account that issued the block must be unaffected by that block. -- The time of the slot commitment must be used to align the local version of the BIC vector with the objective, committed version. -It allows for the global control of the BIC dynamic with a Mana decay function. - - This decrease is also applied to the potential and stored Mana (that can be allotted to the account as BIC) so users cannot gain by delaying or advancing the allotting. -- The balance of the BIC vector at the slot commitment must be the sum of: + * A global agreement on the BIC balances among all the nodes is required. + - It can be achieved by including the BIC vector in the slot commitments. This guarantees that all nodes have +the same perception of the BIC balances from a certain point in time. + * If a block is orphaned, the block will not be included in a commitment, and hence, the balance of BIC of the +account that issued the block must be unaffected by that block. + * The time of the slot commitment must be used to align the local version of the BIC vector with the objective, +committed version. It allows for the global control of the BIC dynamic with a Mana decay function. + - This decrease is also applied to the potential and stored Mana (that can be allotted to the account as BIC) +so users cannot gain by delaying or advancing the allotting. + * The balance of the BIC vector at the slot commitment must be the sum of: - The balances of the previously committed BIC vector. - - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of only decaying the BIC vector at the end of each epoch, this Mana would have to be decayed by a factor proportional to the difference between the transaction slot index and the index of the last slot of the epoch. However, since the decay rate is small, this difference will be always smaller than half a percent. We understand that this difference (since it's not composable and can only be "taken profit of" once) does not justify the user experience-related issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being allotted in a transaction. + - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of +only decaying the BIC vector at the end of each epoch, this Mana would have to be decayed by a factor proportional +to the difference between the transaction slot index and the index of the last slot of the epoch. However, since the +decay rate is small, this difference will always be smaller than half a percent. We understand that this difference +(since it is not composable and can only be "taken profit of" once) does not justify the user experience-related +issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and +implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being +allotted in a transaction. - Subtract from BIC all Mana burned by accepted blocks of the committed slots. -- BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the end of the epoch. -- Mana decay must be applied at the end of epoch according to the algorithm: - - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an epoch. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC, by applying: - -``` + * BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the +end of each epoch. + * Mana decay must be applied at the end of the epoch according to the algorithm: + - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an epoch. +This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now +decay the remaining value of BIC by applying: + +```go if BIC > 0: - new_BIC = decay(BIC,1) + new_BIC = decay(BIC, 1) else: new_BIC = BIC - ``` - -If `i` is not the last slot of the epoch, this decay should not be applied. - - -- A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. - - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that + + If `i` is not the last slot of the epoch, this decay should not be applied. + * A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. + - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that the account has authorized the block and that Mana can be burned from the BIC of that account. -- The issuer must specify the maximum amount of Mana they will allow to be burned from BIC. - - In the above-mentioned permission, the account owner must commit to a certain maximum amount of Mana that will be burned from BIC. -- The declared burning amount must be at least the required burning for the current slot. - - The required burning amount for a block is calculated with the Reference Mana Cost (RMC), which depends on the past network activity and gets updated every slot. + * The issuer must specify the maximum amount of Mana they will allow to be burned from BIC. + - In the above-mentioned permission, the account owner must commit to a certain maximum amount of Mana that +will be burned from BIC. + * The declared burning amount must be at least the required burning for the current slot. + - The required burning amount for a block is calculated with the Reference Mana Cost (RMC), which depends on +the past network activity and gets updated every slot. ## Mana rewards -*Mana rewards* are used to reward for participation in staking for validation and delegating IOTA tokens. -Rewarding validators and delegators with Mana is reasonable as it does not extract value from other IOTA token holders. +*Mana rewards* are used to reward for participation in staking for validation and delegating IOTA tokens. Rewarding +validators and delegators with Mana is reasonable as it does not extract value from other IOTA token holders. ### Mana Rewards Semantic Validation -- Mana rewards must be calculated on a per-epoch basis. -- Mana rewards must become available for claiming when the last slot of the epoch is committed to. -- Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. -- Mana rewards must be put on outputs as stored Mana on the output side of the transaction. -- The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: - - Let `reward`, `rewardEpoch`, and `claimingSlotEpoch` be as follows: + + * Mana rewards must be calculated on a per-epoch basis. + * Mana rewards must become available for claiming when the last slot of the epoch is committed to. + * Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or +delegated. + * Mana rewards must be put on outputs as stored Mana on the output side of the transaction. + * The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: + - Let `reward`, `rewardEpoch`, and `claimingSlotEpoch` be as follows: @@ -574,23 +612,19 @@ Rewarding validators and delegators with Mana is reasonable as it does not extra
Name
- - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the lookup table and the algorithm defined in the section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the rewards, by applying: - - - ``` - reward = decay(reward,n) - ``` + - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the lookup table and the algorithm +defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the +rewards by applying `reward = decay(reward, n)`. - If `n = 0`, the amount to be put on outputs is the entire `reward`. - - ## Data Types & Subschema Notation Data types and subschemas used throughout this TIP are defined in [TIP-21](../TIP-0021/tip-0021.md). ## Global Protocol Parameters -Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA)](../TIP-0022/tip-0022.md) and [TIP-32 (Shimmer)](../TIP-0032/tip-0032.md). +Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA)](../TIP-0022/tip-0022.md) and +[TIP-32 (Shimmer)](../TIP-0032/tip-0032.md). ## Transaction Payload @@ -598,6 +632,9 @@ Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA ## Lookup Table +== TODO: If this `32` here (and above in pseudo codes) comes from `decayFactorsExponent`, +let's use the `decayFactorsExponent`?== + @@ -2430,8 +2467,6 @@ Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA - - # Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From b022290e6d6682242484d57df7a51665193f1b7e Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Mon, 31 Jul 2023 12:34:26 +0200 Subject: [PATCH 051/157] Minor format correction --- tips/TIP-0039/tip-0039.md | 128 +++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 1794cc6d4..a7170710c 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -61,30 +61,30 @@ fully use all the Mana functionalities, the user is required to have an account, ## Mana design Mana is a core element of the IOTA incentive scheme. It is a resource that can be obtained through: - * generating by holding IOTA tokens; - * as a reward for staking IOTA tokens; - * as a reward for delegating IOTA tokens; - * or simply received from other IOTA users. +- generating by holding IOTA tokens; +- as a reward for staking IOTA tokens; +- as a reward for delegating IOTA tokens; +- or simply received from other IOTA users. It is an essential element of the IOTA protocol, as it is used to: - * determine the allowed throughput of an account; - * as a payment form for the block issuance. +- determine the allowed throughput of an account; +- as a payment form for the block issuance. The following solutions are designed around the newest IOTA Congestion Control Algorithm (ICCA) with Mana Credits. Additionally, Mana implementation is strictly connected to the accounts introduced in [TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivization scheme. **Mana** can have different forms, each of which is described in the following sections. - * [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved +- [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved within certain rules between the different owners, which allows for Mana market development. - * [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. +- [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA tokens. - * When the user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit +- When the user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit form (the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If a user does not store the potential Mana when consuming the output, she will forfeit this Mana. Alternatively, the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). - * [**Mana rewards**](#mana-rewards) are used to reward for participation in staking for validation and delegating IOTA +- [**Mana rewards**](#mana-rewards) are used to reward for participation in staking for validation and delegating IOTA tokens. The Mana rewarded from staking and validation must be claimed and stored as stored Mana. The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. @@ -105,9 +105,9 @@ blocks in slots that are *Maximum Committable Age (MCA)* slots in the past so th RMC and know this value in advance (before issuing the block). From a high-level perspective, the RMC algorithm works as follows: - * If the number of blocks in slot `i - MCA` is larger than a given threshold, then the RMC increases. - * Otherwise, if the activity is low, the RMC decreases. - * The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly +- If the number of blocks in slot `i - MCA` is larger than a given threshold, then the RMC increases. +- Otherwise, if the activity is low, the RMC decreases. +- The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes too large for the majority of users, and activity drops. The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid @@ -122,10 +122,10 @@ generation both from IOTA tokens and the staking mechanism, which will be discus To guarantee non-gameability (e.g., splitting accounts or other behaviors that are not helpful for the system well-functioning cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs to be applied to all forms of Mana: - * newly generated Mana ([Potential Mana](#potential-mana)); - * Mana stored in UTXOs ([Stored Mana](#stored-mana)); - * Mana bound to accounts for block issuance ([Block Issuance Credit](#block-issuance-credit)); - * Mana rewarded for staking and delegation ([Mana rewards](#mana-rewards)). +- newly generated Mana ([Potential Mana](#potential-mana)); +- Mana stored in UTXOs ([Stored Mana](#stored-mana)); +- Mana bound to accounts for block issuance ([Block Issuance Credit](#block-issuance-credit)); +- Mana rewarded for staking and delegation ([Mana rewards](#mana-rewards)). As the form in which the decay factor will be applied might differ among the Mana types, it is essential to point out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper @@ -289,8 +289,8 @@ where the summation is over `i = 1, ..., n - 1`. Analogously, if `n ≤ 1`, we find the following results (here `δ` is the difference between the creation and consumption slots): - * If `n = 1`: `Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2`. - * If `n = 0`: `Potential Mana = γ * S * δ`. +- If `n = 1`: `Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2`. +- If `n = 0`: `Potential Mana = γ * S * δ`. ### Potential Mana formulas with fixed point arithmetics @@ -303,21 +303,21 @@ If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(- `c = decayFactorEpochsSum * 2^(-decayFactorEpochsSumExponent)`. Given the values defined in the last section, we set `decayFactorEpochsSum = TODO` and `decayFactorEpochsSumExponent= TODO`. Then, `Potential_Mana = aux + aux1 + aux2`, where: - * `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; - * `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-decayFactorsExponent) `; - * `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-decayFactorsExponent)`; +- `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; +- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-decayFactorsExponent) `; +- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-decayFactorsExponent)`; and - * `slotPerEpoch = 2^slotsPerEpochExponent` is the number of slots in an epoch. Initially, we use +- `slotPerEpoch = 2^slotsPerEpochExponent` is the number of slots in an epoch. Initially, we use `slotsPerEpochExponent = 13`; - * `d1 = slotAfterEpochi - creationSlot`; - * `slotAfterEpochi` is the first slot of the epoch `i + 1`; - * `d2 = consumptionSlot - firstSlotEpochJ` - * `firstSlotEpochJ` is the first slot of epoch `j` ; - * `generationPerSlot = generationRate * 2^(-generationRateExponent)` is the Mana generated by holding 1 IOTA for +- `d1 = slotAfterEpochi - creationSlot`; +- `slotAfterEpochi` is the first slot of the epoch `i + 1`; +- `d2 = consumptionSlot - firstSlotEpochJ` +- `firstSlotEpochJ` is the first slot of epoch `j` ; +- `generationPerSlot = generationRate * 2^(-generationRateExponent)` is the Mana generated by holding 1 IOTA for 1 slot. Initially, we use `generationRate = 1` and `generationRateExponent = 80 - manaBits`. This generation rate per slot guarantees that the maximum theoretical mana in the system uses the `manaBits` available bits; - * `manaBits = 63`. +- `manaBits = 63`. Note that the term `aux2` has a factor `lookupTable(n - 1) + 1` instead of `lookupTable(n - 1)` since the values in the lookup table are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing @@ -325,32 +325,32 @@ this, we avoid potential gameability scenarios, since all the terms added will b Rearranging the formulas above, we have that `Potential_Mana = potentialMana0 + potentialManan + potentialManan1`, where - * `potentialMana0 = amount * d2 * generationRate * 2^(-generationRateExponent) + c * amount * generationRate * +- `potentialMana0 = amount * d2 * generationRate * 2^(-generationRateExponent) + c * amount * generationRate * 2^(slotsPerEpochExponent - generationRateExponent) - c * amount * generationRate * 2^(slotsPerEpochExponent - decayFactorsExponent - generationRateExponent)`; - * `potentialManan = amount * d1 * lookupTable(n) * generationRate * 2^(-decayFactorsExponent-generationRateExponent)`; - * `potentialManan1 = -c * amount * generationRate * lookupTable(n - 1) * +- `potentialManan = amount * d1 * lookupTable(n) * generationRate * 2^(-decayFactorsExponent-generationRateExponent)`; +- `potentialManan1 = -c * amount * generationRate * lookupTable(n - 1) * 2^(slotsPerEpochExponent - decayFactorsExponent - generationRateExponent)`. Analogously, we find formulas for `n < 2`: - * If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * generationRate * +- If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * generationRate * 2^(-decayFactorsExponent - generationRateExponent) + amount * d2 * generationRate * 2^(-generationRateExponent)`. - * If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * generationRate * +- If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * generationRate * 2^(-generationRateExponent)`. In the next section, we introduce the default implementation for the formulas presented above. ### Potential Mana Semantic Validation - * Potential Mana must and can only be consumed when the corresponding output is consumed. - * When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the +- Potential Mana must and can only be consumed when the corresponding output is consumed. +- When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the accumulated potential Mana value. There are three options: - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be placed in the newly created output on the output side of the transaction; - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance Credit (BIC) should be specified in the `Allotment` field of the transaction; - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. - * The exact algorithm to calculate the Potential Mana generated by an output created at slot `creationSlot` i +- The exact algorithm to calculate the Potential Mana generated by an output created at slot `creationSlot` i (which has an epoch `creationEpoch`) and consumed at slot `consumptionSlot` (which has an epoch `consumptionEpoch`), holding `Amount` IOTA tokens, is given by (again, in the pseudocode below, `slotAfterCreationEpoch` is the first slot of the epoch after the creation epoch and `firstSlotConsumptionEpoch` is the first slot of the consumption @@ -438,17 +438,17 @@ being applied to it. ### Stored Mana Semantic Validation - * Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. - * Stored Mana must be soulbound to an account. - * Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be spent within a block. It must +- Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. +- Stored Mana must be soulbound to an account. +- Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be spent within a block. It must be allotted to an account's BIC in order to pay for Mana burned by blocks. - * *Mana Sales Outputs* must be used for transferring stored or potential Mana freely from one account to another. - * It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from +- *Mana Sales Outputs* must be used for transferring stored or potential Mana freely from one account to another. +- It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from those tokens. - * The decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. - * To calculate the decay of stored Mana, the creation time of each output with stored Mana must be contained in +- The decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. +- To calculate the decay of stored Mana, the creation time of each output with stored Mana must be contained in transactions. - * The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: +- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: - Let `manaAmount`, `consumptionSlot`, and `creationSlot`, be
Lookup Table: Decays for Mana in decay index granularity scaled to 2^32
n 3131131867
@@ -508,32 +508,32 @@ why Mana cannot be burned from BIC by a transaction; it can only be burned by a ### Block Issuance Credit Semantic Validation - * Block issuance credits must be stored on a per-account basis. - * Accounts must be represented by _Account Outputs_ on the UTXO ledger. The cost of permanently storing any outputs +- Block issuance credits must be stored on a per-account basis. +- Accounts must be represented by _Account Outputs_ on the UTXO ledger. The cost of permanently storing any outputs (until destruction) in the ledger is covered by the _storage deposit_. Because of that, the number of accounts is capped at a number proportional to the max supply of tokens, contrary to the number of plain addresses. Because BIC must be tracked in slot commitments, keeping the number of entries (even though the user can create multiple accounts) in that data structure as small as possible is desirable. Using account IDs for that purpose is thus a good fit. - * It is not possible to store BIC without an Account Output because Mana burned by blocks must also be deducted +- It is not possible to store BIC without an Account Output because Mana burned by blocks must also be deducted from BIC, and the block cannot modify the Account Output. Consequently, the ledger state is not bloated by having to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that requires a storage deposit in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the block issuance credits. - * A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. +- A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. - The end time of an epoch is used for the decay calculations. - Definition of slots based on the time of the genesis slot and slot duration. - A commitment mechanism per slot is needed to ensure the unified perception of the BIC in the longer run. - * A global agreement on the BIC balances among all the nodes is required. +- A global agreement on the BIC balances among all the nodes is required. - It can be achieved by including the BIC vector in the slot commitments. This guarantees that all nodes have the same perception of the BIC balances from a certain point in time. - * If a block is orphaned, the block will not be included in a commitment, and hence, the balance of BIC of the +- If a block is orphaned, the block will not be included in a commitment, and hence, the balance of BIC of the account that issued the block must be unaffected by that block. - * The time of the slot commitment must be used to align the local version of the BIC vector with the objective, +- The time of the slot commitment must be used to align the local version of the BIC vector with the objective, committed version. It allows for the global control of the BIC dynamic with a Mana decay function. - This decrease is also applied to the potential and stored Mana (that can be allotted to the account as BIC) so users cannot gain by delaying or advancing the allotting. - * The balance of the BIC vector at the slot commitment must be the sum of: +- The balance of the BIC vector at the slot commitment must be the sum of: - The balances of the previously committed BIC vector. - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of only decaying the BIC vector at the end of each epoch, this Mana would have to be decayed by a factor proportional @@ -544,9 +544,9 @@ issues (like having to allot more than 1 Mana to being able to burn 1 Mana in th implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being allotted in a transaction. - Subtract from BIC all Mana burned by accepted blocks of the committed slots. - * BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the +- BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the end of each epoch. - * Mana decay must be applied at the end of the epoch according to the algorithm: +- Mana decay must be applied at the end of the epoch according to the algorithm: - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an epoch. This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now decay the remaining value of BIC by applying: @@ -558,14 +558,14 @@ else: new_BIC = BIC ``` - If `i` is not the last slot of the epoch, this decay should not be applied. - * A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. +If `i` is not the last slot of the epoch, this decay should not be applied. +- A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that the account has authorized the block and that Mana can be burned from the BIC of that account. - * The issuer must specify the maximum amount of Mana they will allow to be burned from BIC. +- The issuer must specify the maximum amount of Mana they will allow to be burned from BIC. - In the above-mentioned permission, the account owner must commit to a certain maximum amount of Mana that will be burned from BIC. - * The declared burning amount must be at least the required burning for the current slot. +- The declared burning amount must be at least the required burning for the current slot. - The required burning amount for a block is calculated with the Reference Mana Cost (RMC), which depends on the past network activity and gets updated every slot. @@ -576,12 +576,12 @@ validators and delegators with Mana is reasonable as it does not extract value f ### Mana Rewards Semantic Validation - * Mana rewards must be calculated on a per-epoch basis. - * Mana rewards must become available for claiming when the last slot of the epoch is committed to. - * Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or +- Mana rewards must be calculated on a per-epoch basis. +- Mana rewards must become available for claiming when the last slot of the epoch is committed to. +- Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. - * Mana rewards must be put on outputs as stored Mana on the output side of the transaction. - * The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: +- Mana rewards must be put on outputs as stored Mana on the output side of the transaction. +- The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: - Let `reward`, `rewardEpoch`, and `claimingSlotEpoch` be as follows:
From f91fd85bf474f99a57e8b953c66a987e95f7acc7 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 1 Aug 2023 13:48:17 +0200 Subject: [PATCH 052/157] Fix ToC --- tips/TIP-0039/tip-0039.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index a7170710c..c13465fd2 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -13,28 +13,28 @@ requires: TIP-42 # Table of Contents -- [Table of Contents](#table-of-contents) -- [Summary](#summary) -- [Motivation](#motivation) -- [Building Blocks](#building-blocks) - - [Mana design](#mana-design) - - [Mana burn](#mana-burn) +1. [Summary](#summary) +2. [Motivation](#motivation) +3. [Building Blocks](#building-blocks) + - [Mana Design](#mana-design) + - [Mana Burn](#mana-burn) - [Reference Mana Cost](#reference-mana-cost) - - [Mana decay](#mana-decay) - - [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) - - [How to use the lookup table](#how-to-use-the-lookup-table) + - [Mana Decay](#mana-decay) + - [Mana and Fixed Point Arithmetics](#mana-and-fixed-point-arithmetics) + - [How To Use the Lookup Table](#how-to-use-the-lookup-table) - [Potential Mana](#potential-mana) - [Potential Mana Semantic Validation](#potential-mana-semantic-validation) - [Stored Mana](#stored-mana) - [Stored Mana Semantic Validation](#stored-mana-semantic-validation) - [Block Issuance Credit](#block-issuance-credit) - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) - - [Mana rewards](#mana-rewards) + - [Mana Rewards](#mana-rewards) - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) - [Data Types \& Subschema Notation](#data-types--subschema-notation) - [Global Protocol Parameters](#global-protocol-parameters) - [Transaction Payload](#transaction-payload) -- [Copyright](#copyright) + - [Lookup Table](#lookup-table) +4. [Copyright](#copyright) # Summary From 33291bb814e53ad3bf7ca15da11d115c8717c486 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 1 Aug 2023 13:52:36 +0200 Subject: [PATCH 053/157] Fix ToC indentation --- tips/TIP-0039/tip-0039.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c13465fd2..841e6e263 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -16,24 +16,24 @@ requires: TIP-42 1. [Summary](#summary) 2. [Motivation](#motivation) 3. [Building Blocks](#building-blocks) - - [Mana Design](#mana-design) - - [Mana Burn](#mana-burn) - - [Reference Mana Cost](#reference-mana-cost) - - [Mana Decay](#mana-decay) - - [Mana and Fixed Point Arithmetics](#mana-and-fixed-point-arithmetics) - - [How To Use the Lookup Table](#how-to-use-the-lookup-table) - - [Potential Mana](#potential-mana) - - [Potential Mana Semantic Validation](#potential-mana-semantic-validation) - - [Stored Mana](#stored-mana) - - [Stored Mana Semantic Validation](#stored-mana-semantic-validation) - - [Block Issuance Credit](#block-issuance-credit) - - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) - - [Mana Rewards](#mana-rewards) - - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) - - [Data Types \& Subschema Notation](#data-types--subschema-notation) - - [Global Protocol Parameters](#global-protocol-parameters) - - [Transaction Payload](#transaction-payload) - - [Lookup Table](#lookup-table) + - [Mana Design](#mana-design) + - [Mana Burn](#mana-burn) + - [Reference Mana Cost](#reference-mana-cost) + - [Mana Decay](#mana-decay) + - [Mana and Fixed Point Arithmetics](#mana-and-fixed-point-arithmetics) + - [How To Use the Lookup Table](#how-to-use-the-lookup-table) + - [Potential Mana](#potential-mana) + - [Potential Mana Semantic Validation](#potential-mana-semantic-validation) + - [Stored Mana](#stored-mana) + - [Stored Mana Semantic Validation](#stored-mana-semantic-validation) + - [Block Issuance Credit](#block-issuance-credit) + - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) + - [Mana Rewards](#mana-rewards) + - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) + - [Data Types \& Subschema Notation](#data-types--subschema-notation) + - [Global Protocol Parameters](#global-protocol-parameters) + - [Transaction Payload](#transaction-payload) + - [Lookup Table](#lookup-table) 4. [Copyright](#copyright) # Summary From d031acbf4a034b941d919774ffa3019e72ce8098 Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 1 Aug 2023 14:04:24 +0200 Subject: [PATCH 054/157] Add refs to the lookup table --- tips/TIP-0039/tip-0039.md | 79 +++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 841e6e263..14c17a730 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -16,19 +16,19 @@ requires: TIP-42 1. [Summary](#summary) 2. [Motivation](#motivation) 3. [Building Blocks](#building-blocks) - - [Mana Design](#mana-design) - - [Mana Burn](#mana-burn) + - [Mana design](#mana-design) + - [Mana burn](#mana-burn) - [Reference Mana Cost](#reference-mana-cost) - - [Mana Decay](#mana-decay) - - [Mana and Fixed Point Arithmetics](#mana-and-fixed-point-arithmetics) - - [How To Use the Lookup Table](#how-to-use-the-lookup-table) + - [Mana decay](#mana-decay) + - [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) + - [How to use the lookup table](#how-to-use-the-lookup-table) - [Potential Mana](#potential-mana) - [Potential Mana Semantic Validation](#potential-mana-semantic-validation) - [Stored Mana](#stored-mana) - [Stored Mana Semantic Validation](#stored-mana-semantic-validation) - [Block Issuance Credit](#block-issuance-credit) - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) - - [Mana Rewards](#mana-rewards) + - [Mana rewards](#mana-rewards) - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) - [Data Types \& Subschema Notation](#data-types--subschema-notation) - [Global Protocol Parameters](#global-protocol-parameters) @@ -158,7 +158,7 @@ calculations have to be done with fixed point arithmetics. In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. -Specifically, the lookup table introduced is an integer approximation of +Specifically, the ([Lookup Table](#lookup-table)) introduced is an integer approximation of `2^decayFactorsExponent * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, for different values of `n`. We set `decayFactorsExponent = 32`, `epochDuration = 10 * 2^slotsPerEpochExponent = 10 * 2^13` seconds (which means that the duration of an epoch in @@ -171,7 +171,7 @@ years is around `0.002597666159`), and `β = 1/3` per year. In this section, we define a function `decay(value, n)`, that decays an amount on Mana `value` by the factor relative to `n` epochs. Note that the table defined above only gives the values of `lookupTable(n)` for some i values of `n` up to `maxDecayFactor = 365`. To calculate `decay(value, n)` for larger values of `n`, we combine -values defined in the lookup table for other numbers smaller than `365`, using an algorithm that will be defined +values defined in the ([Lookup Table](#lookup-table)) for other numbers smaller than `365`, using an algorithm that will be defined below. First, we define three auxiliary functions: ```go @@ -297,7 +297,7 @@ consumption slots): The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated `2^decayFactorsExponent * exp(-β * Δ * i)` by -`lookupTable(i)`, where `decayFactorsExponent` is the precision of the lookup table used. +`lookupTable(i)`, where `decayFactorsExponent` is the precision of the [Lookup Table](#lookup-table) used. If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form `c = decayFactorEpochsSum * 2^(-decayFactorEpochsSumExponent)`. Given the values defined in the last section, @@ -320,7 +320,7 @@ per slot guarantees that the maximum theoretical mana in the system uses the `ma - `manaBits = 63`. Note that the term `aux2` has a factor `lookupTable(n - 1) + 1` instead of `lookupTable(n - 1)` since the values -in the lookup table are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing +in the [Lookup Table](#lookup-table) are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing this, we avoid potential gameability scenarios, since all the terms added will be rounded down in the formula. Rearranging the formulas above, we have that `Potential_Mana = potentialMana0 + potentialManan + potentialManan1`, @@ -357,34 +357,33 @@ slot of the epoch after the creation epoch and `firstSlotConsumptionEpoch` is t epoch) the algorithms define below.
- - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
Valueuint64 - The amount of IOTA tokens held in the output. -
creationSlotuint64 - The index of slot in which the output was created. -
consumptionSlotuint64 - The index of slot in which the output is consumed. -
- + + Name + Type + Description + + + Value + uint64 + + The amount of IOTA tokens held in the output. + + + + creationSlot + uint64 + + The index of slot in which the output was created. + + + + consumptionSlot + uint64 + + The index of slot in which the output is consumed. + + + ==TODO: talk about the missing remainder== @@ -451,7 +450,7 @@ transactions. - The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: - Let `manaAmount`, `consumptionSlot`, and `creationSlot`, be - +
@@ -612,7 +611,7 @@ delegated.
Name Type
- - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the lookup table and the algorithm + - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the [Lookup Table](#lookup-table) and the algorithm defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the rewards by applying `reward = decay(reward, n)`. - If `n = 0`, the amount to be put on outputs is the entire `reward`. From 7ed14b02b2b92b995c13fda64237891f2a1fc35d Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Tue, 1 Aug 2023 14:27:59 +0200 Subject: [PATCH 055/157] Add mana decay params table --- tips/TIP-0039/tip-0039.md | 81 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 14c17a730..6224e00ef 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -20,6 +20,7 @@ requires: TIP-42 - [Mana burn](#mana-burn) - [Reference Mana Cost](#reference-mana-cost) - [Mana decay](#mana-decay) + - [Mana decay parameters](#mana-decay-parameters) - [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) - [How to use the lookup table](#how-to-use-the-lookup-table) - [Potential Mana](#potential-mana) @@ -145,6 +146,76 @@ supply to get to this value, nobody can spend their Mana for years. In practice, way smaller than `2^manaBits - 1`, however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. +### Mana decay parameters + +The table below describes the key parameters used for the Mana decay calculations in the next sections of this TIP. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription
β + Global exponential decay parameter. +
γ + Defines fixed potential Mana generation per slot. +
manaBits + Defines the number of bits used to represent Mana in the system. +
slotDuration + The duration of a slot. +
slotsPerEpochExponent + Defines the number of slots per epoch. +
epochDuration + The duration of an epoch. +
decayFactorsExponent + Defines the precision of the lookup table. +
maxDecayFactor + The maximum epoch value presented in the lookup table. +
decayFactorEpochsSum + TODO +
decayFactorEpochsSumExponent + TODO +
+ ## Mana and fixed point arithmetics Floating point operations might lead to inconsistencies among results in different nodes due to the different @@ -158,7 +229,7 @@ calculations have to be done with fixed point arithmetics. In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. -Specifically, the ([Lookup Table](#lookup-table)) introduced is an integer approximation of +Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of `2^decayFactorsExponent * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, for different values of `n`. We set `decayFactorsExponent = 32`, `epochDuration = 10 * 2^slotsPerEpochExponent = 10 * 2^13` seconds (which means that the duration of an epoch in @@ -171,7 +242,7 @@ years is around `0.002597666159`), and `β = 1/3` per year. In this section, we define a function `decay(value, n)`, that decays an amount on Mana `value` by the factor relative to `n` epochs. Note that the table defined above only gives the values of `lookupTable(n)` for some i values of `n` up to `maxDecayFactor = 365`. To calculate `decay(value, n)` for larger values of `n`, we combine -values defined in the ([Lookup Table](#lookup-table)) for other numbers smaller than `365`, using an algorithm that will be defined +values defined in the [lookup table](#lookup-table) for other numbers smaller than `365`, using an algorithm that will be defined below. First, we define three auxiliary functions: ```go @@ -297,7 +368,7 @@ consumption slots): The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for `n > 1`, noticing that we already approximated `2^decayFactorsExponent * exp(-β * Δ * i)` by -`lookupTable(i)`, where `decayFactorsExponent` is the precision of the [Lookup Table](#lookup-table) used. +`lookupTable(i)`, where `decayFactorsExponent` is the precision of the [lookup table](#lookup-table) used. If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form `c = decayFactorEpochsSum * 2^(-decayFactorEpochsSumExponent)`. Given the values defined in the last section, @@ -320,7 +391,7 @@ per slot guarantees that the maximum theoretical mana in the system uses the `ma - `manaBits = 63`. Note that the term `aux2` has a factor `lookupTable(n - 1) + 1` instead of `lookupTable(n - 1)` since the values -in the [Lookup Table](#lookup-table) are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing +in the [lookup table](#lookup-table) are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing this, we avoid potential gameability scenarios, since all the terms added will be rounded down in the formula. Rearranging the formulas above, we have that `Potential_Mana = potentialMana0 + potentialManan + potentialManan1`, @@ -611,7 +682,7 @@ delegated. - - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the [Lookup Table](#lookup-table) and the algorithm + - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the [lookup table](#lookup-table) and the algorithm defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the rewards by applying `reward = decay(reward, n)`. - If `n = 0`, the amount to be put on outputs is the entire `reward`. From b071c24d60e61e99c7b56fb94ea8790a75c1a541 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 4 Sep 2023 09:52:03 +0100 Subject: [PATCH 056/157] Update tip-0039.md change the phrasing about manaBits --- tips/TIP-0039/tip-0039.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 6224e00ef..b7e8c721c 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -139,11 +139,11 @@ any of those cases, the node must calculate the decay based on epoch indices, no slots will be in the same epoch. We set `slotsPerEpochExponent = 13`. The decay parameter `β` (together with the Mana generation parameter) was set so the maximum theoretical Mana in -the system is `2^manaBits - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses +the system is smaller than `2^manaBits - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses `manaBits < 64` bits (in the case of BIC, it uses at most `manaBits + 1` bits, `manaBits` for the value and one -for the sign). Note that this value of `2^manaBits - 1` will almost certainly never be achieved since for the Mana -supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with values -way smaller than `2^manaBits - 1`, however, we must count on what would be an unreasonably large value in practice +for the sign). Note that the system will almost certainly never use all the `manaBits` to store Mana, since, for the Mana +supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with Mana values +way smaller than `2^manaBits - 1`; however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. ### Mana decay parameters From 9ca8e07a229ef85df60f0a4547aa462422bc1f4d Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Tue, 5 Sep 2023 18:16:59 +0100 Subject: [PATCH 057/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 207 ++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 84 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index b7e8c721c..462a94d7b 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -148,7 +148,8 @@ to avoid overflowing of the variables, even if with a really small probability. ### Mana decay parameters -The table below describes the key parameters used for the Mana decay calculations in the next sections of this TIP. +The tables below describe the key parameters used for the Mana decay calculations in the next sections of this TIP. Notice that the parameters in the first table are only used in the explanations in this TIP, but not in the code. + @@ -166,56 +167,99 @@ The table below describes the key parameters used for the Mana decay calculation Defines fixed potential Mana generation per slot. - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - -
Name
manaBits - Defines the number of bits used to represent Mana in the system. -
slotDuration - The duration of a slot. -
slotsPerEpochExponent - Defines the number of slots per epoch. -
epochDuration
Epoch Duration The duration of an epoch.
decayFactorsExponent - Defines the precision of the lookup table. -
maxDecayFactor - The maximum epoch value presented in the lookup table. -
decayFactorEpochsSum - TODO -
decayFactorEpochsSumExponent - TODO -
+The second table describes the key parameters used for the Mana decay calculations in the next sections of this TIP, as they are used in the code. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Mana Bits uint8 + Mana Bits is the number of bits used to represent Mana. +
Mana Bits Exponentuint8 + Mana Bits Exponent is the number of bits used to represent Mana expressed as an exponent of 2. +
Slot Duration In Secondsuint8 + Slot Duration In Seconds defines the duration of each slot in seconds. +
Slots Per Epoch Exponentuint8 + Slots Per Epoch Exponent is the number of slots in an epoch expressed as an exponent of 2. (2**SlotsPerEpochExponent) == slots in an epoch. +
Mana Generation Rateuint8 + Mana Generation Rate is the amount of potential Mana generated by 1 IOTA in 1 slot. +
Mana Generation Rate Exponentuint8 + Mana Generation Rate Exponent is the scaling of Mana Generation Rate expressed as an exponent of 2. +
Mana Decay Factors Lengthuint16 + The length of Mana Decay Factors. +
Mana Decay Factorsuint32Array + Mana Decay Factors is a lookup table of epoch index diff to mana decay factor (slice index 0 = 1 epoch). +
Mana Decay Factors Exponentuint8 + Mana Decay Factors Exponent is the scaling of ManaDecayFactors expressed as an exponent of 2. +
Mana Decay Factor Epochs Sumuint32 + Mana Decay Factor Epochs Sum is an integer approximation of the sum of decay over epochs. +
Mana Decay Factor Epochs Sum Exponentuint8 + Mana Decay Factor Epochs Sum Exponent is the scaling of Mana Decay Factor Epochs Sum expressed as an exponent of 2. +
+ + + + + ## Mana and fixed point arithmetics Floating point operations might lead to inconsistencies among results in different nodes due to the different @@ -230,18 +274,16 @@ calculations have to be done with fixed point arithmetics. In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of -`2^decayFactorsExponent * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, -for different values of `n`. We set `decayFactorsExponent = 32`, +`2^manaDecayFactorsLength * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, +for different values of `n`. We set `manaDecayFactorsLength = 32`, `epochDuration = 10 * 2^slotsPerEpochExponent = 10 * 2^13` seconds (which means that the duration of an epoch in years is around `0.002597666159`), and `β = 1/3` per year. ### How to use the lookup table -==TODO: decide to max epoch in the table, if it's 365 or if we are adding values per year in the end== - In this section, we define a function `decay(value, n)`, that decays an amount on Mana `value` by the factor relative to `n` epochs. Note that the table defined above only gives the values of `lookupTable(n)` for some i -values of `n` up to `maxDecayFactor = 365`. To calculate `decay(value, n)` for larger values of `n`, we combine +values of `n` up to `365`. To calculate `decay(value, n)` for larger values of `n`, we combine values defined in the [lookup table](#lookup-table) for other numbers smaller than `365`, using an algorithm that will be defined below. First, we define three auxiliary functions: @@ -304,15 +346,15 @@ func decay(value, n) { remainingEpochs = n while remainingEpochs > 0 { EpochsToDecay = remainingEpochs - if EpochsToDecay > maxDecayFactor { - EpochsToDecay = maxDecayFactor + if EpochsToDecay > 365 { + EpochsToDecay = 365 } remainingEpochs -= EpochsToDecay decayFactor = lookupTable(EpochsToDecay) // apply the decay using fixed-point arithmetics. - valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, decayFactor, decayFactorsExponent) + valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, decayFactor, manaDecayFactorsLength) } // combine both uint64 variables to get the actual value @@ -330,10 +372,7 @@ If someone did this operation in a different order, let's say `1002 * 21 / 100 * ## Potential Mana -==TODO : check if storage deposit ctually generate mana== - -*Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token, whether -storage deposit or not, generates potential Mana. The view on the potential Mana value can be deterministically +*Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token (besides storage deposits) generates potential Mana. The view on the potential Mana value can be deterministically derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created in the UTXO metadata (we consider the creation time as the slot index of the transaction). @@ -367,16 +406,16 @@ consumption slots): The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the -formula for `n > 1`, noticing that we already approximated `2^decayFactorsExponent * exp(-β * Δ * i)` by -`lookupTable(i)`, where `decayFactorsExponent` is the precision of the [lookup table](#lookup-table) used. +formula for `n > 1`, noticing that we already approximated `2^manaDecayFactorsLength * exp(-β * Δ * i)` by +`lookupTable(i)`, where `manaDecayFactorsLength` is the precision of the [lookup table](#lookup-table) used. If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form -`c = decayFactorEpochsSum * 2^(-decayFactorEpochsSumExponent)`. Given the values defined in the last section, -we set `decayFactorEpochsSum = TODO` and `decayFactorEpochsSumExponent= TODO`. Then, +`c = manaDecayFactorEpochsSum * 2^(-manaDecayFactorEpochsSumExponent)`. Given the values defined in the last section, +we set `manaDecayFactorEpochsSum = TODO` and `manaDecayFactorEpochsSumExponent= TODO`. Then, `Potential_Mana = aux + aux1 + aux2`, where: - `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; -- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-decayFactorsExponent) `; -- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-decayFactorsExponent)`; +- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-manaDecayFactorsLength) `; +- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-manaDecayFactorsLength)`; and - `slotPerEpoch = 2^slotsPerEpochExponent` is the number of slots in an epoch. Initially, we use @@ -385,8 +424,8 @@ and - `slotAfterEpochi` is the first slot of the epoch `i + 1`; - `d2 = consumptionSlot - firstSlotEpochJ` - `firstSlotEpochJ` is the first slot of epoch `j` ; -- `generationPerSlot = generationRate * 2^(-generationRateExponent)` is the Mana generated by holding 1 IOTA for -1 slot. Initially, we use `generationRate = 1` and `generationRateExponent = 80 - manaBits`. This generation rate +- `generationPerSlot = manaGenerationRate * 2^(-manaGenerationRateExponent)` is the Mana generated by holding 1 IOTA for +1 slot. Initially, we use `manaGenerationRate = 1` and `manaGenerationRateExponent = 80 - manaBits`. This generation rate per slot guarantees that the maximum theoretical mana in the system uses the `manaBits` available bits; - `manaBits = 63`. @@ -396,18 +435,18 @@ this, we avoid potential gameability scenarios, since all the terms added will b Rearranging the formulas above, we have that `Potential_Mana = potentialMana0 + potentialManan + potentialManan1`, where -- `potentialMana0 = amount * d2 * generationRate * 2^(-generationRateExponent) + c * amount * generationRate * -2^(slotsPerEpochExponent - generationRateExponent) - c * amount * generationRate * -2^(slotsPerEpochExponent - decayFactorsExponent - generationRateExponent)`; -- `potentialManan = amount * d1 * lookupTable(n) * generationRate * 2^(-decayFactorsExponent-generationRateExponent)`; -- `potentialManan1 = -c * amount * generationRate * lookupTable(n - 1) * -2^(slotsPerEpochExponent - decayFactorsExponent - generationRateExponent)`. +- `potentialMana0 = amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent) + c * amount * manaGenerationRate * +2^(slotsPerEpochExponent - manaGenerationRateExponent) - c * amount * manaGenerationRate * +2^(slotsPerEpochExponent - manaDecayFactorsLength - manaGenerationRateExponent)`; +- `potentialManan = amount * d1 * lookupTable(n) * manaGenerationRate * 2^(-manaDecayFactorsLength-manaGenerationRateExponent)`; +- `potentialManan1 = -c * amount * manaGenerationRate * lookupTable(n - 1) * +2^(slotsPerEpochExponent - manaDecayFactorsLength - manaGenerationRateExponent)`. Analogously, we find formulas for `n < 2`: -- If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * generationRate * -2^(-decayFactorsExponent - generationRateExponent) + amount * d2 * generationRate * 2^(-generationRateExponent)`. -- If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * generationRate * -2^(-generationRateExponent)`. +- If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * manaGenerationRate * +2^(-manaDecayFactorsLength - manaGenerationRateExponent) + amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent)`. +- If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * manaGenerationRate * +2^(-manaGenerationRateExponent)`. In the next section, we introduce the default implementation for the formulas presented above. @@ -464,10 +503,10 @@ We begin by defining an auxiliary function that (intuitively) generates Mana wit ```go // generateMana calculates the generated mana from holding `value` tokens for `m` slots, without applying any decay. func generateMana(value, m) { - if m == 0 or generationRate == 0 { + if m == 0 or manaGenerationRate == 0 { return 0 } - return MultiplicationAndShift(value, m * generationRate, generationRateExponent) + return MultiplicationAndShift(value, m * manaGenerationRate, manaGenerationRateExponent) } ``` @@ -483,18 +522,18 @@ func PotentialManaWithDecay(value, n, d1, d2) { else if n == 1: return decay(generateMana(value, d1), 1) + generateMana(value, d2) else: - aux = MultiplicationAndShift(value * generationRate, decayFactorEpochsSum, decayFactorEpochsSumExponent + -generationRateExponent - slotsPerEpochExponent) + aux = MultiplicationAndShift(value * manaGenerationRate, manaDecayFactorEpochsSum, manaDecayFactorEpochsSumExponent + +manaGenerationRateExponent - slotsPerEpochExponent) potentialMana_n := decay(generateMana(value, d1), n) potentialMana_n_1 := decay(aux, n - 1) - potentialMana_0 := generateMana(value, d2) + aux - aux >> decayFactorsExponent + potentialMana_0 := generateMana(value, d2) + aux - aux >> manaDecayFactorsLength return potentialMana_n - potentialMana_n_1 + potentialMana_0 } ``` -==TODO: talk with max about the generationRate in aux and generateMana== +==TODO: talk with max about the manaGenerationRate in aux and generateMana== ## Stored Mana @@ -702,8 +741,8 @@ Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA ## Lookup Table -== TODO: If this `32` here (and above in pseudo codes) comes from `decayFactorsExponent`, -let's use the `decayFactorsExponent`?== +== TODO: If this `32` here (and above in pseudo codes) comes from `manaDecayFactorsLength`, +let's use the `manaDecayFactorsLength`?== From 2bc606789aeb874d6b06f8a891d238ff50403662 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Mon, 11 Sep 2023 09:15:47 +0200 Subject: [PATCH 058/157] Close lookup table, add code tags --- tips/TIP-0039/tip-0039.md | 740 +++++++++++++++++++------------------- 1 file changed, 371 insertions(+), 369 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 462a94d7b..a6ef4adc7 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -744,1837 +744,1839 @@ Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA == TODO: If this `32` here (and above in pseudo codes) comes from `manaDecayFactorsLength`, let's use the `manaDecayFactorsLength`?== -
Lookup Table: Decays for Mana in decay index granularity scaled to 2^32
+
Lookup Table: Decays for Mana in decay index granularity scaled to 2^32
+ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Lookup Table: Decays for Mana in decay index granularity scaled to 2^32
nTypedecay(n)nTypedecay(n)
1 - uint32 uint32 4291249941
2 - uint32 uint32 4287535805
3 - uint32 uint32 4283824883
4 - uint32 uint32 4280117173
5 - uint32 uint32 4276412671
6 - uint32 uint32 4272711377
7 - uint32 uint32 4269013285
8 - uint32 uint32 4265318395
9 - uint32 uint32 4261626702
10 - uint32 uint32 4257938205
11 - uint32 uint32 4254252900
12 - uint32 uint32 4250570785
13 - uint32 uint32 4246891856
14 - uint32 uint32 4243216112
15 - uint32 uint32 4239543550
16 - uint32 uint32 4235874166
17 - uint32 uint32 4232207957
18 - uint32 uint32 4228544922
19 - uint32 uint32 4224885058
20 - uint32 uint32 4221228361
21 - uint32 uint32 4217574829
22 - uint32 uint32 4213924459
23 - uint32 uint32 4210277249
24 - uint32 uint32 4206633195
25 - uint32 uint32 4202992295
26 - uint32 uint32 4199354547
27 - uint32 uint32 4195719947
28 - uint32 uint32 4192088493
29 - uint32 uint32 4188460182
30 - uint32 uint32 4184835011
31 - uint32 uint32 4181212978
32 - uint32 uint32 4177594080
33 - uint32 uint32 4173978314
34 - uint32 uint32 4170365677
35 - uint32 uint32 4166756168
36 - uint32 uint32 4163149782
37 - uint32 uint32 4159546518
38 - uint32 uint32 4155946372
39 - uint32 uint32 4152349343
40 - uint32 uint32 4148755427
41 - uint32 uint32 4145164621
42 - uint32 uint32 4141576923
43 - uint32 uint32 4137992331
44 - uint32 uint32 4134410840
45 - uint32 uint32 4130832450
46 - uint32 uint32 4127257157
47 - uint32 uint32 4123684959
48 - uint32 uint32 4120115852
49 - uint32 uint32 4116549834
50 - uint32 uint32 4112986903
51 - uint32 uint32 4109427055
52 - uint32 uint32 4105870289
53 - uint32 uint32 4102316601
54 - uint32 uint32 4098765988
55 - uint32 uint32 4095218449
56 - uint32 uint32 4091673981
57 - uint32 uint32 4088132580
58 - uint32 uint32 4084594244
59 - uint32 uint32 4081058971
60 - uint32 uint32 4077526757
61 - uint32 uint32 4073997601
62 - uint32 uint32 4070471499
63 - uint32 uint32 4066948449
64 - uint32 uint32 4063428449
65 - uint32 uint32 4059911495
66 - uint32 uint32 4056397585
67 - uint32 uint32 4052886716
68 - uint32 uint32 4049378886
69 - uint32 uint32 4045874092
70 - uint32 uint32 4042372332
71 - uint32 uint32 4038873602
72 - uint32 uint32 4035377901
73 - uint32 uint32 4031885225
74 - uint32 uint32 4028395572
75 - uint32 uint32 4024908939
76 - uint32 uint32 4021425325
77 - uint32 uint32 4017944725
78 - uint32 uint32 4014467138
79 - uint32 uint32 4010992560
80 - uint32 uint32 4007520990
81 - uint32 uint32 4004052425
82 - uint32 uint32 4000586862
83 - uint32 uint32 3997124298
84 - uint32 uint32 3993664731
85 - uint32 uint32 3990208159
86 - uint32 uint32 3986754578
87 - uint32 uint32 3983303986
88 - uint32 uint32 3979856381
89 - uint32 uint32 3976411760
90 - uint32 uint32 3972970120
91 - uint32 uint32 3969531459
92 - uint32 uint32 3966095774
93 - uint32 uint32 3962663063
94 - uint32 uint32 3959233323
95 - uint32 uint32 3955806551
96 - uint32 uint32 3952382745
97 - uint32 uint32 3948961903
98 - uint32 uint32 3945544021
99 - uint32 uint32 3942129098
100 - uint32 uint32 3938717130
101 - uint32 uint32 3935308116
102 - uint32 uint32 3931902052
103 - uint32 uint32 3928498936
104 - uint32 uint32 3925098765
105 - uint32 uint32 3921701537
106 - uint32 uint32 3918307250
107 - uint32 uint32 3914915900
108 - uint32 uint32 3911527486
109 - uint32 uint32 3908142004
110 - uint32 uint32 3904759453
111 - uint32 uint32 3901379829
112 - uint32 uint32 3898003131
113 - uint32 uint32 3894629355
114 - uint32 uint32 3891258499
115 - uint32 uint32 3887890560
116 - uint32 uint32 3884525537
117 - uint32 uint32 3881163426
118 - uint32 uint32 3877804224
119 - uint32 uint32 3874447931
120 - uint32 uint32 3871094542
121 - uint32 uint32 3867744056
122 - uint32 uint32 3864396469
123 - uint32 uint32 3861051780
124 - uint32 uint32 3857709986
125 - uint32 uint32 3854371084
126 - uint32 uint32 3851035072
127 - uint32 uint32 3847701948
128 - uint32 uint32 3844371708
129 - uint32 uint32 3841044351
130 - uint32 uint32 3837719873
131 - uint32 uint32 3834398273
132 - uint32 uint32 3831079548
133 - uint32 uint32 3827763695
134 - uint32 uint32 3824450713
135 - uint32 uint32 3821140597
136 - uint32 uint32 3817833347
137 - uint32 uint32 3814528959
138 - uint32 uint32 3811227431
139 - uint32 uint32 3807928760
140 - uint32 uint32 3804632945
141 - uint32 uint32 3801339982
142 - uint32 uint32 3798049869
143 - uint32 uint32 3794762604
144 - uint32 uint32 3791478184
145 - uint32 uint32 3788196607
146 - uint32 uint32 3784917870
147 - uint32 uint32 3781641970
148 - uint32 uint32 3778368907
149 - uint32 uint32 3775098676
150 - uint32 uint32 3771831275
151 - uint32 uint32 3768566702
152 - uint32 uint32 3765304955
153 - uint32 uint32 3762046031
154 - uint32 uint32 3758789928
155 - uint32 uint32 3755536643
156 - uint32 uint32 3752286174
157 - uint32 uint32 3749038518
158 - uint32 uint32 3745793673
159 - uint32 uint32 3742551636
160 - uint32 uint32 3739312405
161 - uint32 uint32 3736075978
162 - uint32 uint32 3732842352
163 - uint32 uint32 3729611525
164 - uint32 uint32 3726383494
165 - uint32 uint32 3723158258
166 - uint32 uint32 3719935812
167 - uint32 uint32 3716716156
168 - uint32 uint32 3713499286
169 - uint32 uint32 3710285201
170 - uint32 uint32 3707073897
171 - uint32 uint32 3703865373
172 - uint32 uint32 3700659626
173 - uint32 uint32 3697456653
174 - uint32 uint32 3694256453
175 - uint32 uint32 3691059023
176 - uint32 uint32 3687864360
177 - uint32 uint32 3684672462
178 - uint32 uint32 3681483326
179 - uint32 uint32 3678296951
180 - uint32 uint32 3675113334
181 - uint32 uint32 3671932472
182 - uint32 uint32 3668754363
183 - uint32 uint32 3665579005
184 - uint32 uint32 3662406395
185 - uint32 uint32 3659236531
186 - uint32 uint32 3656069411
187 - uint32 uint32 3652905032
188 - uint32 uint32 3649743392
189 - uint32 uint32 3646584488
190 - uint32 uint32 3643428318
191 - uint32 uint32 3640274880
192 - uint32 uint32 3637124172
193 - uint32 uint32 3633976190
194 - uint32 uint32 3630830933
195 - uint32 uint32 3627688398
196 - uint32 uint32 3624548583
197 - uint32 uint32 3621411486
198 - uint32 uint32 3618277104
199 - uint32 uint32 3615145434
200 - uint32 uint32 3612016476
201 - uint32 uint32 3608890225
202 - uint32 uint32 3605766680
203 - uint32 uint32 3602645839
204 - uint32 uint32 3599527699
205 - uint32 uint32 3596412257
206 - uint32 uint32 3593299512
207 - uint32 uint32 3590189461
208 - uint32 uint32 3587082102
209 - uint32 uint32 3583977433
210 - uint32 uint32 3580875450
211 - uint32 uint32 3577776153
212 - uint32 uint32 3574679537
213 - uint32 uint32 3571585602
214 - uint32 uint32 3568494345
215 - uint32 uint32 3565405764
216 - uint32 uint32 3562319855
217 - uint32 uint32 3559236618
218 - uint32 uint32 3556156049
219 - uint32 uint32 3553078146
220 - uint32 uint32 3550002907
221 - uint32 uint32 3546930330
222 - uint32 uint32 3543860413
223 - uint32 uint32 3540793152
224 - uint32 uint32 3537728546
225 - uint32 uint32 3534666593
226 - uint32 uint32 3531607290
227 - uint32 uint32 3528550634
228 - uint32 uint32 3525496624
229 - uint32 uint32 3522445258
230 - uint32 uint32 3519396533
231 - uint32 uint32 3516350446
232 - uint32 uint32 3513306995
233 - uint32 uint32 3510266179
234 - uint32 uint32 3507227995
235 - uint32 uint32 3504192440
236 - uint32 uint32 3501159513
237 - uint32 uint32 3498129210
238 - uint32 uint32 3495101531
239 - uint32 uint32 3492076472
240 - uint32 uint32 3489054031
241 - uint32 uint32 3486034206
242 - uint32 uint32 3483016995
243 - uint32 uint32 3480002395
244 - uint32 uint32 3476990404
245 - uint32 uint32 3473981020
246 - uint32 uint32 3470974241
247 - uint32 uint32 3467970065
248 - uint32 uint32 3464968488
249 - uint32 uint32 3461969510
250 - uint32 uint32 3458973127
251 - uint32 uint32 3455979337
252 - uint32 uint32 3452988139
253 - uint32 uint32 3449999530
254 - uint32 uint32 3447013507
255 - uint32 uint32 3444030069
256 - uint32 uint32 3441049213
257 - uint32 uint32 3438070937
258 - uint32 uint32 3435095238
259 - uint32 uint32 3432122115
260 - uint32 uint32 3429151566
261 - uint32 uint32 3426183587
262 - uint32 uint32 3423218178
263 - uint32 uint32 3420255335
264 - uint32 uint32 3417295056
265 - uint32 uint32 3414337339
266 - uint32 uint32 3411382183
267 - uint32 uint32 3408429584
268 - uint32 uint32 3405479541
269 - uint32 uint32 3402532051
270 - uint32 uint32 3399587112
271 - uint32 uint32 3396644722
272 - uint32 uint32 3393704878
273 - uint32 uint32 3390767579
274 - uint32 uint32 3387832823
275 - uint32 uint32 3384900606
276 - uint32 uint32 3381970927
277 - uint32 uint32 3379043784
278 - uint32 uint32 3376119175
279 - uint32 uint32 3373197097
280 - uint32 uint32 3370277548
281 - uint32 uint32 3367360525
282 - uint32 uint32 3364446028
283 - uint32 uint32 3361534053
284 - uint32 uint32 3358624598
285 - uint32 uint32 3355717662
286 - uint32 uint32 3352813241
287 - uint32 uint32 3349911335
288 - uint32 uint32 3347011940
289 - uint32 uint32 3344115054
290 - uint32 uint32 3341220676
291 - uint32 uint32 3338328803
292 - uint32 uint32 3335439433
293 - uint32 uint32 3332552563
294 - uint32 uint32 3329668193
295 - uint32 uint32 3326786318
296 - uint32 uint32 3323906939
297 - uint32 uint32 3321030051
298 - uint32 uint32 3318155653
299 - uint32 uint32 3315283743
300 - uint32 uint32 3312414319
301 - uint32 uint32 3309547378
302 - uint32 uint32 3306682918
303 - uint32 uint32 3303820938
304 - uint32 uint32 3300961435
305 - uint32 uint32 3298104407
306 - uint32 uint32 3295249852
307 - uint32 uint32 3292397767
308 - uint32 uint32 3289548151
309 - uint32 uint32 3286701001
310 - uint32 uint32 3283856315
311 - uint32 uint32 3281014092
312 - uint32 uint32 3278174328
313 - uint32 uint32 3275337023
314 - uint32 uint32 3272502173
315 - uint32 uint32 3269669777
316 - uint32 uint32 3266839832
317 - uint32 uint32 3264012336
318 - uint32 uint32 3261187288
319 - uint32 uint32 3258364685
320 - uint32 uint32 3255544525
321 - uint32 uint32 3252726806
322 - uint32 uint32 3249911526
323 - uint32 uint32 3247098682
324 - uint32 uint32 3244288273
325 - uint32 uint32 3241480296
326 - uint32 uint32 3238674749
327 - uint32 uint32 3235871631
328 - uint32 uint32 3233070939
329 - uint32 uint32 3230272671
330 - uint32 uint32 3227476825
331 - uint32 uint32 3224683399
332 - uint32 uint32 3221892391
333 - uint32 uint32 3219103798
334 - uint32 uint32 3216317619
335 - uint32 uint32 3213533851
336 - uint32 uint32 3210752492
337 - uint32 uint32 3207973541
338 - uint32 uint32 3205196995
339 - uint32 uint32 3202422853
340 - uint32 uint32 3199651111
341 - uint32 uint32 3196881768
342 - uint32 uint32 3194114823
343 - uint32 uint32 3191350272
344 - uint32 uint32 3188588114
345 - uint32 uint32 3185828346
346 - uint32 uint32 3183070967
347 - uint32 uint32 3180315975
348 - uint32 uint32 3177563367
349 - uint32 uint32 3174813142
350 - uint32 uint32 3172065297
351 - uint32 uint32 3169319830
352 - uint32 uint32 3166576739
353 - uint32 uint32 3163836023
354 - uint32 uint32 3161097679
355 - uint32 uint32 3158361705
356 - uint32 uint32 3155628099
357 - uint32 uint32 3152896859
358 - uint32 uint32 3150167982
359 - uint32 uint32 3147441468
360 - uint32 uint32 3144717314
361 - uint32 uint32 3141995517
362 - uint32 uint32 3139276076
363 - uint32 uint32 3136558989
364 - uint32 uint32 3133844253
365 - uint32 uint32 3131131867
# Copyright From 344aa989c39994419b5d1b5bd224b0f8f040a3c3 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Mon, 11 Sep 2023 09:39:47 +0200 Subject: [PATCH 059/157] Update tips/TIP-0039/tip-0039.md Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index a6ef4adc7..733274c7b 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -296,7 +296,7 @@ func upperBits(value, n){ ``` ```go -// Returns the upper n bits of a uint64 value +// Returns the lower n bits of a uint64 value func lowerBits(value, n){ value = value << (64 - n) value = value >> (64 - n) From a84b83eb695c1daafcd4ceba6463cc97ca080f70 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Mon, 11 Sep 2023 09:43:26 +0200 Subject: [PATCH 060/157] Rename "tokens" to "coins" --- tips/TIP-0039/tip-0039.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 733274c7b..60d7c7698 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -62,9 +62,9 @@ fully use all the Mana functionalities, the user is required to have an account, ## Mana design Mana is a core element of the IOTA incentive scheme. It is a resource that can be obtained through: -- generating by holding IOTA tokens; -- as a reward for staking IOTA tokens; -- as a reward for delegating IOTA tokens; +- generating by holding IOTA coins; +- as a reward for staking IOTA coins; +- as a reward for delegating IOTA coins; - or simply received from other IOTA users. It is an essential element of the IOTA protocol, as it is used to: @@ -78,10 +78,10 @@ Additionally, Mana implementation is strictly connected to the accounts introduc **Mana** can have different forms, each of which is described in the following sections. - [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved within certain rules between the different owners, which allows for Mana market development. -- [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA tokens. +- [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA coins. It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO -that holds the IOTA tokens. -- When the user spends the IOTA tokens, he is obliged to transition accumulated potential Mana to its more explicit +that holds the IOTA coins. +- When the user spends the IOTA coins, he is obliged to transition accumulated potential Mana to its more explicit form (the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If a user does not store the potential Mana when consuming the output, she will forfeit this Mana. Alternatively, the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). @@ -119,7 +119,7 @@ it is proposed to update its value every MCA slot at least. ## Mana decay Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana -generation both from IOTA tokens and the staking mechanism, which will be discussed in detail in the next sections. +generation both from IOTA coins and the staking mechanism, which will be discussed in detail in the next sections. To guarantee non-gameability (e.g., splitting accounts or other behaviors that are not helpful for the system well-functioning cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs to be applied to all forms of Mana: @@ -372,13 +372,13 @@ If someone did this operation in a different order, let's say `1002 * 21 / 100 * ## Potential Mana -*Potential Mana* is a raw form of Mana that is generated over time from the IOTA tokens. Every IOTA token (besides storage deposits) generates potential Mana. The view on the potential Mana value can be deterministically +*Potential Mana* is a raw form of Mana that is generated over time from the IOTA coins. Every IOTA token (besides storage deposits) generates potential Mana. The view on the potential Mana value can be deterministically derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created in the UTXO metadata (we consider the creation time as the slot index of the transaction). ### Rationale behind the Potential Mana formulas -We model the potential Mana generated by an output holding `S` IOTA tokens as the combination of a fixed generation +We model the potential Mana generated by an output holding `S` IOTA coins as the combination of a fixed generation per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time an epoch ends, where `Δ` i is the epoch duration. @@ -462,7 +462,7 @@ Credit (BIC) should be specified in the `Allotment` field of the transaction; - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. - The exact algorithm to calculate the Potential Mana generated by an output created at slot `creationSlot` i (which has an epoch `creationEpoch`) and consumed at slot `consumptionSlot` (which has an epoch `consumptionEpoch`), -holding `Amount` IOTA tokens, is given by (again, in the pseudocode below, `slotAfterCreationEpoch` is the first +holding `Amount` IOTA coins, is given by (again, in the pseudocode below, `slotAfterCreationEpoch` is the first slot of the epoch after the creation epoch and `firstSlotConsumptionEpoch` is the first slot of the consumption epoch) the algorithms define below. @@ -476,7 +476,7 @@ epoch) the algorithms define below. Value uint64 - The amount of IOTA tokens held in the output. + The amount of IOTA coins held in the output. @@ -547,12 +547,12 @@ being applied to it. ### Stored Mana Semantic Validation -- Each output that contains stored Mana must also contain IOTA tokens due to storage deposit requirements. +- Each output that contains stored Mana must also contain IOTA coins due to storage deposit requirements. - Stored Mana must be soulbound to an account. - Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be spent within a block. It must be allotted to an account's BIC in order to pay for Mana burned by blocks. - *Mana Sales Outputs* must be used for transferring stored or potential Mana freely from one account to another. -- It is possible to transfer stored Mana without transferring IOTA tokens or the potential Mana generated from +- It is possible to transfer stored Mana without transferring IOTA coins or the potential Mana generated from those tokens. - The decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. - To calculate the decay of stored Mana, the creation time of each output with stored Mana must be contained in @@ -627,7 +627,7 @@ good fit. - It is not possible to store BIC without an Account Output because Mana burned by blocks must also be deducted from BIC, and the block cannot modify the Account Output. Consequently, the ledger state is not bloated by having to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that -requires a storage deposit in IOTA tokens. Thus, the dust protection mechanism used for the UTXO ledger also +requires a storage deposit in IOTA coins. Thus, the dust protection mechanism used for the UTXO ledger also indirectly prevents dust from accumulating in tracking the block issuance credits. - A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. - The end time of an epoch is used for the decay calculations. @@ -680,7 +680,7 @@ the past network activity and gets updated every slot. ## Mana rewards -*Mana rewards* are used to reward for participation in staking for validation and delegating IOTA tokens. Rewarding +*Mana rewards* are used to reward for participation in staking for validation and delegating IOTA coins. Rewarding validators and delegators with Mana is reasonable as it does not extract value from other IOTA token holders. ### Mana Rewards Semantic Validation From 244c629ac8bc411903f673c6b5949d45966d82cb Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Mon, 11 Sep 2023 09:44:45 +0200 Subject: [PATCH 061/157] Rename "token" to "coin" --- tips/TIP-0039/tip-0039.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 60d7c7698..0a5de2ed7 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -372,8 +372,8 @@ If someone did this operation in a different order, let's say `1002 * 21 / 100 * ## Potential Mana -*Potential Mana* is a raw form of Mana that is generated over time from the IOTA coins. Every IOTA token (besides storage deposits) generates potential Mana. The view on the potential Mana value can be deterministically -derived from the UTXO ledger, based on the UTXO IOTA token value and the time it was created in the UTXO metadata +*Potential Mana* is a raw form of Mana that is generated over time from the IOTA coins. Every IOTA coin (besides storage deposits) generates potential Mana. The view on the potential Mana value can be deterministically +derived from the UTXO ledger, based on the UTXO IOTA coin value and the time it was created in the UTXO metadata (we consider the creation time as the slot index of the transaction). ### Rationale behind the Potential Mana formulas @@ -681,7 +681,7 @@ the past network activity and gets updated every slot. ## Mana rewards *Mana rewards* are used to reward for participation in staking for validation and delegating IOTA coins. Rewarding -validators and delegators with Mana is reasonable as it does not extract value from other IOTA token holders. +validators and delegators with Mana is reasonable as it does not extract value from other IOTA coin holders. ### Mana Rewards Semantic Validation From 31dabcbbe0e5a8356e267887227ebf70251a1438 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 25 Sep 2023 20:28:48 +0100 Subject: [PATCH 062/157] Update tips/TIP-0039/tip-0039.md Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 0a5de2ed7..df24e09d1 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -71,7 +71,7 @@ It is an essential element of the IOTA protocol, as it is used to: - determine the allowed throughput of an account; - as a payment form for the block issuance. -The following solutions are designed around the newest IOTA Congestion Control Algorithm (ICCA) with Mana Credits. +The following solutions are designed around the IOTA Congestion Control Algorithm (ICCA) with Mana Credits. Additionally, Mana implementation is strictly connected to the accounts introduced in [TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivization scheme. From 59a6102818305cfcced47fb56d1908e4dad01616 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 25 Sep 2023 20:32:32 +0100 Subject: [PATCH 063/157] Update tips/TIP-0039/tip-0039.md Co-authored-by: /alex/ --- tips/TIP-0039/tip-0039.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index df24e09d1..37566f605 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -67,8 +67,8 @@ Mana is a core element of the IOTA incentive scheme. It is a resource that can b - as a reward for delegating IOTA coins; - or simply received from other IOTA users. -It is an essential element of the IOTA protocol, as it is used to: -- determine the allowed throughput of an account; +It is an essential element of the IOTA protocol, as it is used: +- to determine the allowed throughput of an account; - as a payment form for the block issuance. The following solutions are designed around the IOTA Congestion Control Algorithm (ICCA) with Mana Credits. From a2b1fb108cd7e51d7db4375e370e6c5f679645d2 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 25 Sep 2023 20:33:27 +0100 Subject: [PATCH 064/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 37566f605..ed4629bdb 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -69,7 +69,7 @@ Mana is a core element of the IOTA incentive scheme. It is a resource that can b It is an essential element of the IOTA protocol, as it is used: - to determine the allowed throughput of an account; -- as a payment form for the block issuance. +- as a payment for block issuance. The following solutions are designed around the IOTA Congestion Control Algorithm (ICCA) with Mana Credits. Additionally, Mana implementation is strictly connected to the accounts introduced in From 714619c61ccedf9456424c4f2a6877f9d9fede80 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 25 Sep 2023 20:38:54 +0100 Subject: [PATCH 065/157] Add files via upload --- tips/TIP-0039/img/slots_potential_mana.png | Bin 0 -> 21097 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tips/TIP-0039/img/slots_potential_mana.png diff --git a/tips/TIP-0039/img/slots_potential_mana.png b/tips/TIP-0039/img/slots_potential_mana.png new file mode 100644 index 0000000000000000000000000000000000000000..bce7c818669d7e1c44508129f31694380986bb74 GIT binary patch literal 21097 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 hI);6UvOkDA7XFI9BBNN*83+8`kd(igCVu Date: Mon, 25 Sep 2023 20:41:08 +0100 Subject: [PATCH 066/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index ed4629bdb..b9e275deb 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -382,7 +382,7 @@ We model the potential Mana generated by an output holding `S` IOTA coins as the per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time an epoch ends, where `Δ` i is the epoch duration. -![](https://hackmd.io/_uploads/Bkzz3PiD2.png) +![](./img/slots_potential_mana.png) ==TODO: FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW== From 78e112be50b0b486aa4fe86aed913c40ebf31af9 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 25 Sep 2023 20:43:12 +0100 Subject: [PATCH 067/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index b9e275deb..3b10b2734 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -384,8 +384,6 @@ is the epoch duration. ![](./img/slots_potential_mana.png) -==TODO: FIX THE FIGURE; IT DOES NOT APPEAR IN THE PREVIEW== - Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n = j - i`, and for the sake of the explanation, assume `n > 1`. All the Mana generated in epoch `i` "crosses" `n` decay boundaries; thus, it must be decayed `n` times. The Mana generated in epoch `i + 1` "crosses" `n - 1` decay boundaries, so it From 0e167274d126c5ef8c153b4923fb7e200e0f9ceb Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 25 Sep 2023 20:50:44 +0100 Subject: [PATCH 068/157] Apply suggestions from code review --- tips/TIP-0039/tip-0039.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 3b10b2734..620bc2a02 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -139,11 +139,11 @@ any of those cases, the node must calculate the decay based on epoch indices, no slots will be in the same epoch. We set `slotsPerEpochExponent = 13`. The decay parameter `β` (together with the Mana generation parameter) was set so the maximum theoretical Mana in -the system is smaller than `2^manaBits - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses -`manaBits < 64` bits (in the case of BIC, it uses at most `manaBits + 1` bits, `manaBits` for the value and one -for the sign). Note that the system will almost certainly never use all the `manaBits` to store Mana, since, for the Mana +the system is smaller than `2^manaBitsCount - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses +`manaBitsCount < 64` bits (in the case of BIC, it uses at most `manaBitsCount + 1` bits, `manaBitsCount` for the value and one +for the sign). Note that the system will almost certainly never use all the `manaBitsCount` to store Mana, since, for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with Mana values -way smaller than `2^manaBits - 1`; however, we must count on what would be an unreasonably large value in practice +way smaller than `2^manaBitsCount - 1`; however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. ### Mana decay parameters @@ -423,9 +423,9 @@ and - `d2 = consumptionSlot - firstSlotEpochJ` - `firstSlotEpochJ` is the first slot of epoch `j` ; - `generationPerSlot = manaGenerationRate * 2^(-manaGenerationRateExponent)` is the Mana generated by holding 1 IOTA for -1 slot. Initially, we use `manaGenerationRate = 1` and `manaGenerationRateExponent = 80 - manaBits`. This generation rate -per slot guarantees that the maximum theoretical mana in the system uses the `manaBits` available bits; -- `manaBits = 63`. +1 slot. Initially, we use `manaGenerationRate = 1` and `manaGenerationRateExponent = 80 - manaBitsCount`. This generation rate +per slot guarantees that the maximum theoretical mana in the system uses the `manaBitsCount` available bits; +- `manaBitsCount = 63`. Note that the term `aux2` has a factor `lookupTable(n - 1) + 1` instead of `lookupTable(n - 1)` since the values in the [lookup table](#lookup-table) are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing From 2d780c7497a8d6e086579078ba781c89b20cdc48 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Tue, 26 Sep 2023 09:45:10 +0100 Subject: [PATCH 069/157] Update motivation --- tips/TIP-0039/tip-0039.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 620bc2a02..997a9b126 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -52,8 +52,8 @@ blocks, so it plays the core role in the IOTA tokenomics. The following document Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, delegation, and congestion control changes. This document works with the Congestion Control Algorithm with Mana Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of Mana is burned in each -block, which is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to -their account to increase their BIC and ensure it does not go negative. In order to issue blocks, allot Mana, and +block and is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to +their account to increase their BIC and ensure it does not go negative. In order to issue blocks and fully use all the Mana functionalities, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). From 7109793d0d304b455219be03298a8402c9ff5085 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Tue, 26 Sep 2023 13:20:00 +0100 Subject: [PATCH 070/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 997a9b126..c274e9328 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -62,7 +62,7 @@ fully use all the Mana functionalities, the user is required to have an account, ## Mana design Mana is a core element of the IOTA incentive scheme. It is a resource that can be obtained through: -- generating by holding IOTA coins; +- generation by holding IOTA coins; - as a reward for staking IOTA coins; - as a reward for delegating IOTA coins; - or simply received from other IOTA users. From 1b955edc98f649129d3aefc5ef91708aa0c11307 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Tue, 26 Sep 2023 14:25:49 +0100 Subject: [PATCH 071/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c274e9328..c5ae8bef5 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -81,14 +81,17 @@ within certain rules between the different owners, which allows for Mana market - [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA coins. It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA coins. -- When the user spends the IOTA coins, he is obliged to transition accumulated potential Mana to its more explicit +When the user spends the IOTA coins, he is obliged to transition accumulated potential Mana to its more explicit form (the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If a user does not store the potential Mana when consuming the output, she will forfeit this Mana. Alternatively, the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). -- [**Mana rewards**](#mana-rewards) are used to reward for participation in staking for validation and delegating IOTA -tokens. The Mana rewarded from staking and validation must be claimed and stored as stored Mana. +- [**Mana rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA tokens. +- The Mana rewarded from staking and validation can be technically considered as potential Mana, since it's a +form of Mana not directly registered in the ledger. However, we usually refer to potential Mana when discussing the Mana +generated by holding IOTA tokens and to Mana Rewards when discussing rewards. Mana Rewards must be always claimed and +stored as stored Mana. -The **Mana holdings** are referred to as the sum of all the potential Mana and stored Mana that the user owns. +The **Mana holdings** are the sum of all the potential Mana and stored Mana that the user owns (but not the Mana rewards). ## Mana burn From e5fe9b96b35730ff225a3602347fb7616e64498d Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Tue, 26 Sep 2023 14:27:12 +0100 Subject: [PATCH 072/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c5ae8bef5..acd6f3ad3 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -96,7 +96,7 @@ The **Mana holdings** are the sum of all the potential Mana and stored Mana that ## Mana burn According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a -certain amount of Mana dictated by the size of the block and the Reference Mana Cost (RMC). The Mana burned by the +certain amount of Mana dictated by the work score of the block and the Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Therefore, in order to prevent being locked out of their account, the block issuer must ensure that sufficient Mana is also allotted to their account to ensure their BIC balance remains non-negative. From e028bb87eb38664a5a75cae758724d315604256c Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Tue, 26 Sep 2023 14:30:56 +0100 Subject: [PATCH 073/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index acd6f3ad3..f5a092eda 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -97,9 +97,8 @@ The **Mana holdings** are the sum of all the potential Mana and stored Mana that According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a certain amount of Mana dictated by the work score of the block and the Reference Mana Cost (RMC). The Mana burned by the -block is subtracted from the block issuer's BIC balance. Therefore, in order to prevent being locked out of their -account, the block issuer must ensure that sufficient Mana is also allotted to their account to ensure their BIC -balance remains non-negative. +block is subtracted from the block issuer's BIC balance. Users who overspend Mana (i.e., try to issue more blocks +than their Mana Holdings allow) will have their account locked until their debt is paid. ### Reference Mana Cost From 0d1379d889d6777857f284bd3c5cd028df71c132 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:16:19 +0100 Subject: [PATCH 074/157] Update tips/TIP-0039/tip-0039.md Co-authored-by: Thibault Martinez --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index f5a092eda..35d5fba43 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -283,7 +283,7 @@ years is around `0.002597666159`), and `β = 1/3` per year. ### How to use the lookup table -In this section, we define a function `decay(value, n)`, that decays an amount on Mana `value` by the factor +In this section, we define a function `decay(value, n)`, that decays an amount of Mana `value` by the factor relative to `n` epochs. Note that the table defined above only gives the values of `lookupTable(n)` for some i values of `n` up to `365`. To calculate `decay(value, n)` for larger values of `n`, we combine values defined in the [lookup table](#lookup-table) for other numbers smaller than `365`, using an algorithm that will be defined From dc13b467e6894ca8d04dedcf4a4e5142aadca524 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:16:39 +0100 Subject: [PATCH 075/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 35d5fba43..fbb812214 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -172,7 +172,7 @@ The tables below describe the key parameters used for the Mana decay calculation Epoch Duration - The duration of an epoch. + The duration of an epoch in seconds. From d5b0e884ceb320a6c37dece492ed72023a4b2ade Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:16:48 +0100 Subject: [PATCH 076/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index fbb812214..669fd67be 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -130,7 +130,7 @@ to be applied to all forms of Mana: - Mana bound to accounts for block issuance ([Block Issuance Credit](#block-issuance-credit)); - Mana rewarded for staking and delegation ([Mana rewards](#mana-rewards)). -As the form in which the decay factor will be applied might differ among the Mana types, it is essential to point +As the exact formulas in which the decay factor will be applied might differ among the Mana types, it is essential to point out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. From daea43020f587d1aadc2699f72610a84f7a242fb Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:16:57 +0100 Subject: [PATCH 077/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 669fd67be..f3f503aa8 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -134,7 +134,7 @@ As the exact formulas in which the decay factor will be applied might differ amo out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. -Applying decay for the generation of new Mana and staking rewards is straightforward since it is done at the time of +Applying decay for the generation of new Mana and staking rewards is conceptually straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every `2^slotsPerEpochExponent` slots, the epoch changes, meaning that every set of consecutive `2^slotsPerEpochExponent` From b1fd1f0eac37aecc81f98ecec8bdfa1570ea89f9 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:17:31 +0100 Subject: [PATCH 078/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index f3f503aa8..c8d446c2f 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -181,7 +181,7 @@ The second table describes the key parameters used for the Mana decay calculatio - + - - - - From 80512f397fdcb2c948543c7a33148a5e03beb646 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:18:28 +0100 Subject: [PATCH 080/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 464473320..e7e7cf0c5 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -259,7 +259,7 @@ The second table describes the key parameters used for the Mana decay calculatio ## Mana and fixed point arithmetics Floating point operations might lead to inconsistencies among results in different nodes due to the different -rounding behavior in different architectures. The results of the operations involving floating point variables might +rounding behaviors in different architectures. The results of the operations involving floating point variables might differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, differences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviors in the From 37e4927ea6a32f2ceedbb8f18c8359214dbc99a1 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:18:53 +0100 Subject: [PATCH 081/157] Update tips/TIP-0039/tip-0039.md Co-authored-by: Thibault Martinez --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index e7e7cf0c5..8af0690fd 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -81,7 +81,7 @@ within certain rules between the different owners, which allows for Mana market - [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA coins. It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA coins. -When the user spends the IOTA coins, he is obliged to transition accumulated potential Mana to its more explicit +When users spend the IOTA coins, they are obliged to transition accumulated potential Mana to its more explicit form (the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If a user does not store the potential Mana when consuming the output, she will forfeit this Mana. Alternatively, the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). From f26aab456c56fedee9e5d23bfb3c4f61686040de Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:19:03 +0100 Subject: [PATCH 082/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 8af0690fd..7c01ce58f 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -184,7 +184,7 @@ The second table describes the key parameters used for the Mana decay calculatio From 4164efce82691b8ed270b38fb61f04fed1565664 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:19:18 +0100 Subject: [PATCH 083/157] Update tips/TIP-0039/tip-0039.md Co-authored-by: Thibault Martinez --- tips/TIP-0039/tip-0039.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 7c01ce58f..71206800c 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -82,8 +82,8 @@ within certain rules between the different owners, which allows for Mana market It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO that holds the IOTA coins. When users spend the IOTA coins, they are obliged to transition accumulated potential Mana to its more explicit -form (the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If a user does not store -the potential Mana when consuming the output, she will forfeit this Mana. Alternatively, the user can convert Mana +form (the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If users does not store +the potential Mana when consuming the output, they will forfeit this Mana. Alternatively, the user can convert Mana to [**Block Issuance Credit**](#block-issuance-credit) (BIC). - [**Mana rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA tokens. - The Mana rewarded from staking and validation can be technically considered as potential Mana, since it's a From 9a08c61fd30c54088781c0f409b973f7881e703e Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 27 Sep 2023 10:24:35 +0200 Subject: [PATCH 084/157] Polish motivation --- tips/TIP-0039/tip-0039.md | 54 ++++++++++++--------------------------- 1 file changed, 16 insertions(+), 38 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 71206800c..418c77e7f 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -45,17 +45,10 @@ The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Ma # Motivation -Mana is a resource used to determine the allowed throughput of a user and as a payment form for block issuance -in the Mana burn mechanism. Mana can be obtained by helpful and profitable actions for the network, like token -holding or engagement in securing the network. Additionally, owning Mana is necessary to use the network by issuing -blocks, so it plays the core role in the IOTA tokenomics. The following document gives a high-level overview of -Mana types and dynamics. Mana is a key point of all changes introduced in the IOTA 2.0 protocol, such as staking, -delegation, and congestion control changes. This document works with the Congestion Control Algorithm with Mana -Credits (IOTA 2.0 version of the Congestion Control mechanism), in which a certain amount of Mana is burned in each -block and is deducted from the issuing account's Block Issuance Credit (BIC). A block issuer must allot Mana to -their account to increase their BIC and ensure it does not go negative. In order to issue blocks and -fully use all the Mana functionalities, the user is required to have an account, which is introduced in -[TIP-42](../TIP-0042/tip-0042.md). +Mana is a resource used to determine the allowed throughput of a user and as a payment form for block issuance. Mana can be obtained by constructive and profitable actions for the network, like token holding or engagement in securing the network. Additionally, owning Mana is necessary to use the network by issuing +blocks, so it plays a core role in the IOTA Tokenomics. The following document gives a high-level overview of +Mana types and its dynamics. Mana is a crucial change introduced in the IOTA 2.0 protocol, next to staking, +delegation and congestion control changes. This document works with the Congestion Control Algorithm with Mana, in which block issuers must allot Mana to their account to increase their Block Issuance Credit balance. In order to issue a block a certain amount of BIC is deducted from the issuer account balance and burned. In order to issue blocks and use all functionalitiy related to Mana, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). # Building Blocks @@ -65,37 +58,22 @@ Mana is a core element of the IOTA incentive scheme. It is a resource that can b - generation by holding IOTA coins; - as a reward for staking IOTA coins; - as a reward for delegating IOTA coins; -- or simply received from other IOTA users. +- or simply received or bought from other IOTA users. It is an essential element of the IOTA protocol, as it is used: -- to determine the allowed throughput of an account; -- as a payment for block issuance. - -The following solutions are designed around the IOTA Congestion Control Algorithm (ICCA) with Mana Credits. -Additionally, Mana implementation is strictly connected to the accounts introduced in -[TIP-42](../TIP-0042/tip-0042.md) and is the core point of the IOTA incentivization scheme. +- to determine the allowed throughput of an account in the congestion control; +- as a payment for block issuance; +- as a core part of the IOTA Tokenomics and incentivization scheme. **Mana** can have different forms, each of which is described in the following sections. -- [**Stored Mana**](#stored-mana) is the main form of Mana. It is the UTXO-based form of Mana that can be moved -within certain rules between the different owners, which allows for Mana market development. -- [**Potential Mana**](#potential-mana) is the second form of Mana, which is generated by holding IOTA coins. -It represents the newly generated Mana amounts from the IOTA holdings and is implicitly connected to the UTXO -that holds the IOTA coins. -When users spend the IOTA coins, they are obliged to transition accumulated potential Mana to its more explicit -form (the aforementioned stored Mana), and store the resource directly in the UTXO ledger. If users does not store -the potential Mana when consuming the output, they will forfeit this Mana. Alternatively, the user can convert Mana -to [**Block Issuance Credit**](#block-issuance-credit) (BIC). -- [**Mana rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA tokens. -- The Mana rewarded from staking and validation can be technically considered as potential Mana, since it's a -form of Mana not directly registered in the ledger. However, we usually refer to potential Mana when discussing the Mana -generated by holding IOTA tokens and to Mana Rewards when discussing rewards. Mana Rewards must be always claimed and -stored as stored Mana. - -The **Mana holdings** are the sum of all the potential Mana and stored Mana that the user owns (but not the Mana rewards). - -## Mana burn - -According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a +- [**Stored Mana**](#stored-mana) is Mana that is stored in UTXOs and can consequently be moved on the UTXO ledger, which allows for Mana Market development. +- [**Potential Mana**](#potential-mana) is generated by holding IOTA coins. The longer the IOTA coins were unspent, the more Potential Mana is generated. When an output is spent, its Potential Mana is released and can be transitioned to one of its more explicit forms, i.e. Stored Mana or Block Issuance Credits. +- [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana that can be used to issue blocks. During a transaction, Stored or Potential Mana can be _allotted_ which moves the Mana off the UTXO ledger and converts it to BIC. Only this form of Mana be used to issue blocks. +- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA tokens. The Mana rewarded from these activities is not registered in the UTXO ledger and must be moved to it when claiming rewards as described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). + +## Mana Burn + +The **Mana holdings** of a user is the sum of all the Potential Mana and Stored Mana (but not the Mana Rewards) in their Account Output which they use to issue blocks. According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a certain amount of Mana dictated by the work score of the block and the Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Users who overspend Mana (i.e., try to issue more blocks than their Mana Holdings allow) will have their account locked until their debt is paid. From daa0ea06773e08b0214f41251c54537282f838c7 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 27 Sep 2023 10:26:48 +0200 Subject: [PATCH 085/157] Move building blocks to where they belong --- tips/TIP-0039/tip-0039.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 418c77e7f..4cb4b8e41 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -16,6 +16,8 @@ requires: TIP-42 1. [Summary](#summary) 2. [Motivation](#motivation) 3. [Building Blocks](#building-blocks) + - [Data Types \& Subschema Notation](#data-types--subschema-notation) + - [Protocol Parameters](#protocol-parameters) - [Mana design](#mana-design) - [Mana burn](#mana-burn) - [Reference Mana Cost](#reference-mana-cost) @@ -31,8 +33,6 @@ requires: TIP-42 - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) - [Mana rewards](#mana-rewards) - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) - - [Data Types \& Subschema Notation](#data-types--subschema-notation) - - [Global Protocol Parameters](#global-protocol-parameters) - [Transaction Payload](#transaction-payload) - [Lookup Table](#lookup-table) 4. [Copyright](#copyright) @@ -52,6 +52,14 @@ delegation and congestion control changes. This document works with the Congesti # Building Blocks +## Data Types & Subschema Notation + +Data types and subschemas used throughout this TIP are defined in [TIP-21](../TIP-0021/tip-0021.md). + +## Protocol Parameters + +Protocol parameters used throughout this TIP are defined in [TIP-49](../TIP-0049/tip-0049.md). + ## Mana design Mana is a core element of the IOTA incentive scheme. It is a resource that can be obtained through: @@ -698,15 +706,6 @@ defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arit rewards by applying `reward = decay(reward, n)`. - If `n = 0`, the amount to be put on outputs is the entire `reward`. -## Data Types & Subschema Notation - -Data types and subschemas used throughout this TIP are defined in [TIP-21](../TIP-0021/tip-0021.md). - -## Global Protocol Parameters - -Global protocol parameters used throughout this TIP are defined in [TIP-22 (IOTA)](../TIP-0022/tip-0022.md) and -[TIP-32 (Shimmer)](../TIP-0032/tip-0032.md). - ## Transaction Payload [TIP-20](../TIP-0020/tip-0020.md) is the basis for output validation in this TIP. From fac5937313cd255dcfa62bc490916a00b1044f8d Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 27 Sep 2023 10:29:42 +0200 Subject: [PATCH 086/157] Capitalize headers --- tips/TIP-0039/tip-0039.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 4cb4b8e41..23c32a0cd 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -18,11 +18,11 @@ requires: TIP-42 3. [Building Blocks](#building-blocks) - [Data Types \& Subschema Notation](#data-types--subschema-notation) - [Protocol Parameters](#protocol-parameters) - - [Mana design](#mana-design) - - [Mana burn](#mana-burn) +4. [Mana design](#mana-design) + - [Mana Burn](#mana-burn) - [Reference Mana Cost](#reference-mana-cost) - - [Mana decay](#mana-decay) - - [Mana decay parameters](#mana-decay-parameters) + - [Mana Decay](#mana-decay) + - [Mana Decay Parameters](#mana-decay-parameters) - [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) - [How to use the lookup table](#how-to-use-the-lookup-table) - [Potential Mana](#potential-mana) @@ -35,7 +35,7 @@ requires: TIP-42 - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) - [Transaction Payload](#transaction-payload) - [Lookup Table](#lookup-table) -4. [Copyright](#copyright) +5. [Copyright](#copyright) # Summary @@ -60,7 +60,7 @@ Data types and subschemas used throughout this TIP are defined in [TIP-21](../TI Protocol parameters used throughout this TIP are defined in [TIP-49](../TIP-0049/tip-0049.md). -## Mana design +# Mana Design Mana is a core element of the IOTA incentive scheme. It is a resource that can be obtained through: - generation by holding IOTA coins; @@ -104,7 +104,7 @@ price manipulations by malicious actors. Note that blocks from issuers with nega respect to the RMC calculation, but they do make part of the slot commitment. To limit fluctuations in the RMC, it is proposed to update its value every MCA slot at least. -## Mana decay +## Mana Decay Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA coins and the staking mechanism, which will be discussed in detail in the next sections. @@ -134,7 +134,7 @@ supply to get to this value, nobody can spend their Mana for years. In practice, way smaller than `2^manaBitsCount - 1`; however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. -### Mana decay parameters +### Mana Decay Parameters The tables below describe the key parameters used for the Mana decay calculations in the next sections of this TIP. Notice that the parameters in the first table are only used in the explanations in this TIP, but not in the code. From ea7e609fc88fd69e1d3abb7bbad08a37446ccecb Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 10:28:30 +0100 Subject: [PATCH 087/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 23c32a0cd..e38e97609 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -124,7 +124,7 @@ Applying decay for the generation of new Mana and staking rewards is conceptuall storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every `2^slotsPerEpochExponent` slots, the epoch changes, meaning that every set of consecutive `2^slotsPerEpochExponent` -slots will be in the same epoch. We set `slotsPerEpochExponent = 13`. +slots will be in the same epoch. The decay parameter `β` (together with the Mana generation parameter) was set so the maximum theoretical Mana in the system is smaller than `2^manaBitsCount - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses From bbc2aba5d4f281a424259685b39b24bebbfe5ab7 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 27 Sep 2023 11:48:58 +0200 Subject: [PATCH 088/157] Start adding mana TX validation rules --- tips/TIP-0039/tip-0039.md | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 23c32a0cd..8ea6b67dc 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -33,7 +33,7 @@ requires: TIP-42 - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) - [Mana rewards](#mana-rewards) - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) - - [Transaction Payload](#transaction-payload) + - [Mana Transaction Validation Rules](#) - [Lookup Table](#lookup-table) 5. [Copyright](#copyright) @@ -521,9 +521,8 @@ manaGenerationRateExponent - slotsPerEpochExponent) tokens) of Mana that can be transferred within certain rules between different users, which allows for Mana market development. -All output types, except Foundry Outputs, can hold stored Mana in the *Mana Amount* field. This field represents the -amount of stored Mana at the output's creation time until the time when the output is consumed without decay -being applied to it. +All output types, except Foundry and Delegation Outputs, can hold stored Mana in the *Mana* field. This field represents the +amount of stored Mana at the output's creation time until the time when the output is consumed without decay applied to it. ### Stored Mana Semantic Validation @@ -706,9 +705,30 @@ defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arit rewards by applying `reward = decay(reward, n)`. - If `n = 0`, the amount to be put on outputs is the entire `reward`. -## Transaction Payload +## Mana Transaction Validation Rules -[TIP-20](../TIP-0020/tip-0020.md) is the basis for output validation in this TIP. +| :warning: Work in Progress | +|----------------------------| + +- Let `Total Mana In` be the total amount of Mana on the input side of a transaction, consisting of `Total Potential Mana + Total Stored Mana + Total Mana Rewards`, where: + - `Transaction Creation Slot` is the `Creation Slot` of the transaction, + - `Output Creation Slot` is the `Creation Slot` of the output. + - `Total Potential Mana` is the sum of Potential Mana for each input `i`: + - where its Potential Mana is calculcated as `Potential Mana(Generation Amount, Output Creation Slot, Transaction Creation Slot)` according to [Potential Mana](#potential-mana) where: + - `Generation Amount` is defined as `Amount_i - Min Deposit`, if `Min Deposit > Amount_i`, otherwise `0`, where: + - `Amount_i` is the `Amount` of `i`, + - `Min Deposit` is the minimum necessary storage deposit of `i`. + - `Total Stored Mana` is the sum of Stored Mana for each input `i`: + - where its Stored Mana is calculated as `Stored Mana(Stored Mana_i, Output Creation Slot, Transaction Creation Slot)`, where: + - `Stored Mana_i` is the `Mana` of `i`. + - `Total Mana Rewards` is the sum of Mana Rewards for each input referenced by a _Reward Input_ in the transaction. + +A transaction is only valid if `Total Mana In >= Total Mana Out`. + +| :warning: Potential Overflows | +|-------------------------------| + +It is highly recommended to use safe math to avoid over- and underflows when calculating Mana balances. ## Lookup Table From 9da068d324b2c10bfe4f52d999301f5250c5ef13 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 27 Sep 2023 11:49:54 +0200 Subject: [PATCH 089/157] Fix Mana TX valid. rules ToC --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 39933ee62..60ec86165 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -33,7 +33,7 @@ requires: TIP-42 - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) - [Mana rewards](#mana-rewards) - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) - - [Mana Transaction Validation Rules](#) + - [Mana Transaction Validation Rules](#mana-transaction-validation-rules) - [Lookup Table](#lookup-table) 5. [Copyright](#copyright) From 6554f220e913602185b9b8353fcbd5e2d35c9c84 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 27 Sep 2023 11:51:40 +0200 Subject: [PATCH 090/157] Clarify overflow check recommendation --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 60ec86165..478de548f 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -728,7 +728,7 @@ A transaction is only valid if `Total Mana In >= Total Mana Out`. | :warning: Potential Overflows | |-------------------------------| -It is highly recommended to use safe math to avoid over- and underflows when calculating Mana balances. +It is highly recommended to use overflow checks for arithmetic operations when calculating Mana balances to avoid over- and underflows. ## Lookup Table From 2b594890e29bc6835fe79d742123c783851fb2af Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 27 Sep 2023 12:02:47 +0200 Subject: [PATCH 091/157] Add `Total Mana Out` --- tips/TIP-0039/tip-0039.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 478de548f..13f2541a1 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -707,9 +707,6 @@ rewards by applying `reward = decay(reward, n)`. ## Mana Transaction Validation Rules -| :warning: Work in Progress | -|----------------------------| - - Let `Total Mana In` be the total amount of Mana on the input side of a transaction, consisting of `Total Potential Mana + Total Stored Mana + Total Mana Rewards`, where: - `Transaction Creation Slot` is the `Creation Slot` of the transaction, - `Output Creation Slot` is the `Creation Slot` of the output. @@ -722,6 +719,9 @@ rewards by applying `reward = decay(reward, n)`. - where its Stored Mana is calculated as `Stored Mana(Stored Mana_i, Output Creation Slot, Transaction Creation Slot)`, where: - `Stored Mana_i` is the `Mana` of `i`. - `Total Mana Rewards` is the sum of Mana Rewards for each input referenced by a _Reward Input_ in the transaction. +- Let `Total Mana Out` be the total amount of Mana on the output side of a transaction, consisting of `Total Stored Mana + Total Allotted Mana`, where: + - `Total Stored Mana` is the sum of `Mana` in each output. + - `Total Allotted Mana` is the sum of `Mana` in each _Allotment_. A transaction is only valid if `Total Mana In >= Total Mana Out`. From b5bf888f748eae4a98c58f3d83d8197901365a62 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 27 Sep 2023 12:07:53 +0200 Subject: [PATCH 092/157] Add note on mana rewards decay --- tips/TIP-0039/tip-0039.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 13f2541a1..7e1904154 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -718,7 +718,8 @@ rewards by applying `reward = decay(reward, n)`. - `Total Stored Mana` is the sum of Stored Mana for each input `i`: - where its Stored Mana is calculated as `Stored Mana(Stored Mana_i, Output Creation Slot, Transaction Creation Slot)`, where: - `Stored Mana_i` is the `Mana` of `i`. - - `Total Mana Rewards` is the sum of Mana Rewards for each input referenced by a _Reward Input_ in the transaction. + - `Total Mana Rewards` is the sum of decayed Mana Rewards for each input referenced by a _Reward Input_ in the transaction. + - TODO: We should make a function to calculate the decayed Mana Rewards as well, even if the node usually returns the rewards already in decayed form. - Let `Total Mana Out` be the total amount of Mana on the output side of a transaction, consisting of `Total Stored Mana + Total Allotted Mana`, where: - `Total Stored Mana` is the sum of `Mana` in each output. - `Total Allotted Mana` is the sum of `Mana` in each _Allotment_. From 8ac20221ed56b95306060d54dcb8e692304f9dbe Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 16:10:26 +0100 Subject: [PATCH 093/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 7e1904154..36a6bbb0c 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -269,13 +269,7 @@ values of `n` up to `365`. To calculate `decay(value, n)` for larger values of ` values defined in the [lookup table](#lookup-table) for other numbers smaller than `365`, using an algorithm that will be defined below. First, we define three auxiliary functions: -```go -// Returns the upper n bits of a uint64 value -func upperBits(value, n){ - value = value >> n - return value -} -``` +- `upperBits(value, n)`: given a `uint64` integer `value`, returns its upper `n` bits ```go // Returns the lower n bits of a uint64 value From 4a22ef31d4e52d959e1fc783ac6aed57859ed98b Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 16:11:51 +0100 Subject: [PATCH 094/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 36a6bbb0c..024177c1e 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -271,14 +271,7 @@ below. First, we define three auxiliary functions: - `upperBits(value, n)`: given a `uint64` integer `value`, returns its upper `n` bits -```go -// Returns the lower n bits of a uint64 value -func lowerBits(value, n){ - value = value << (64 - n) - value = value >> (64 - n) - return value -} -``` +- `lowerBits(value, n)`: given a `uint64` integer `value`, returns its lower `n` bits ```go // Returns the result of the multiplication ((valueHi << 32 + valueLo) * multFactor) >> shiftFactor From b1a4f9259e3c48516507d7ed7667bc0c0740ffa8 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 16:12:52 +0100 Subject: [PATCH 095/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 024177c1e..88007eca9 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -273,6 +273,7 @@ below. First, we define three auxiliary functions: - `lowerBits(value, n)`: given a `uint64` integer `value`, returns its lower `n` bits +- `MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the result of a multiplication of a `uint64` by a `uint32`, shifted `shiftFactor` times to the right, whenever this result is smaller than `2^64`. To do so, if uses the following algorithm: ```go // Returns the result of the multiplication ((valueHi << 32 + valueLo) * multFactor) >> shiftFactor // (where multFactor is a uint32, valueHi and valueLo are uint64 smaller than 2^32, and 0 <= shiftFactor <= 32), From 73b75953b0889d04b79cb0ef4e2411128846d064 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 17:37:43 +0100 Subject: [PATCH 096/157] Apply suggestions from code review --- tips/TIP-0039/tip-0039.md | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 88007eca9..04918ff0e 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -274,30 +274,15 @@ below. First, we define three auxiliary functions: - `lowerBits(value, n)`: given a `uint64` integer `value`, returns its lower `n` bits - `MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the result of a multiplication of a `uint64` by a `uint32`, shifted `shiftFactor` times to the right, whenever this result is smaller than `2^64`. To do so, if uses the following algorithm: -```go -// Returns the result of the multiplication ((valueHi << 32 + valueLo) * multFactor) >> shiftFactor -// (where multFactor is a uint32, valueHi and valueLo are uint64 smaller than 2^32, and 0 <= shiftFactor <= 32), -// using only uint64 multiplication functions, without overflowing. The returned result is split in 2 factors: -// valueHi and valueLo, one containing the upper 32 bits of the result and the other containing the lower 32 bits. -func MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor) (uint64, uint64) { - // multiply the integer part of valueHi by multFactor - valueHi = valueHi * multFactor +- Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than `2^64`, `multFactor` be an integer smaller than `2^32`, and `shiftFactor` be an integer between 0 and 32. +- Let `>>` be a right shift (thus, `>>n` means shifting to the right `n`times). Analogously, let `<<` be a left shift. +- Then , apply: - // the lower shiftFactor bits of the result are extracted and shifted left to form the remainder. - // valueLo is multiplied by multFactor and right-shifted by shiftFactor bits. - // the sum of these two values forms the new lower part (valueLo) of the result. + valueHi = valueHi * multFactor valueLo = lowerBits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor - - // the right-shifted valueHi and the upper 32 bits of valueLo form the new higher part (valueHi) of the result. valueHi = (valueHi >> shiftFactor) + upperBits(valueLo, 32) - - // the lower 32 bits of valueLo form the new lower part of the result. valueLo = lowerBits(valueLo, 32) - - // return the result as a fixed-point number composed of two 64-bit integers - return valueHi, valueLo -} -``` + The function returns `valueHi, valueLo`, which represent the 32 upper bits and the 32 lower bits (respectively) of the desired result. With the functions above defined, we proceed to define the `decay` function that takes as input a `uint64` value `value` and decays it by the correct decay factor relative to `n` epochs. From 33eb1b3c5d7be2e971f1fd012bee614f1c39fb8b Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 17:39:01 +0100 Subject: [PATCH 097/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 04918ff0e..037c32a09 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -270,19 +270,18 @@ values defined in the [lookup table](#lookup-table) for other numbers smaller th below. First, we define three auxiliary functions: - `upperBits(value, n)`: given a `uint64` integer `value`, returns its upper `n` bits - - `lowerBits(value, n)`: given a `uint64` integer `value`, returns its lower `n` bits - -- `MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the result of a multiplication of a `uint64` by a `uint32`, shifted `shiftFactor` times to the right, whenever this result is smaller than `2^64`. To do so, if uses the following algorithm: -- Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than `2^64`, `multFactor` be an integer smaller than `2^32`, and `shiftFactor` be an integer between 0 and 32. -- Let `>>` be a right shift (thus, `>>n` means shifting to the right `n`times). Analogously, let `<<` be a left shift. -- Then , apply: - +- `MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the result of a multiplication of a `uint64` by a `uint32`, shifted `shiftFactor` times to the right, whenever this result is smaller than `2^64`. To do so, it uses the following algorithm: + - Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than `2^64`, `multFactor` be an integer smaller than `2^32`, and `shiftFactor` be an integer between 0 and 32. + - Let `>>` be a right shift (thus, `>>n` means shifting to the right `n` times). Analogously, let `<<` be a left shift. + - Then, apply: + ``` valueHi = valueHi * multFactor valueLo = lowerBits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor valueHi = (valueHi >> shiftFactor) + upperBits(valueLo, 32) valueLo = lowerBits(valueLo, 32) - The function returns `valueHi, valueLo`, which represent the 32 upper bits and the 32 lower bits (respectively) of the desired result. + ``` + - The function returns `valueHi, valueLo`, which represent the 32 upper bits and the 32 lower bits (respectively) of the desired result. With the functions above defined, we proceed to define the `decay` function that takes as input a `uint64` value `value` and decays it by the correct decay factor relative to `n` epochs. From eb4ee1b0f82c9199c91ac6c3c9ac2f0608c2020a Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 17:42:03 +0100 Subject: [PATCH 098/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 037c32a09..7202e85da 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -257,7 +257,7 @@ In the last section of this TIP, we introduce a lookup table that will be used i other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of `2^manaDecayFactorsLength * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, -for different values of `n`. We set `manaDecayFactorsLength = 32`, +for different values of `n`. For the lookup Table in this document, we set `manaDecayFactorsLength = 32`, `epochDuration = 10 * 2^slotsPerEpochExponent = 10 * 2^13` seconds (which means that the duration of an epoch in years is around `0.002597666159`), and `β = 1/3` per year. From baa883b535e24ea08cc462abf999d6a7ce4b68d6 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 18:00:19 +0100 Subject: [PATCH 099/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 7202e85da..0cf7d030e 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -256,8 +256,8 @@ calculations have to be done with fixed point arithmetics. In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of -`2^manaDecayFactorsLength * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, -for different values of `n`. For the lookup Table in this document, we set `manaDecayFactorsLength = 32`, +`2^Mana Decay Factors Length * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, +for different values of `n`. For the lookup Table in this document, we set `Mana Decay Factors Length = 32`, `epochDuration = 10 * 2^slotsPerEpochExponent = 10 * 2^13` seconds (which means that the duration of an epoch in years is around `0.002597666159`), and `β = 1/3` per year. @@ -308,7 +308,7 @@ func decay(value, n) { decayFactor = lookupTable(EpochsToDecay) // apply the decay using fixed-point arithmetics. - valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, decayFactor, manaDecayFactorsLength) + valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, decayFactor, Mana Decay Factors Length) } // combine both uint64 variables to get the actual value @@ -358,16 +358,16 @@ consumption slots): The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the -formula for `n > 1`, noticing that we already approximated `2^manaDecayFactorsLength * exp(-β * Δ * i)` by -`lookupTable(i)`, where `manaDecayFactorsLength` is the precision of the [lookup table](#lookup-table) used. +formula for `n > 1`, noticing that we already approximated `2^Mana Decay Factors Length * exp(-β * Δ * i)` by +`lookupTable(i)`, where `Mana Decay Factors Length` is the precision of the [lookup table](#lookup-table) used. If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form `c = manaDecayFactorEpochsSum * 2^(-manaDecayFactorEpochsSumExponent)`. Given the values defined in the last section, we set `manaDecayFactorEpochsSum = TODO` and `manaDecayFactorEpochsSumExponent= TODO`. Then, `Potential_Mana = aux + aux1 + aux2`, where: - `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; -- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-manaDecayFactorsLength) `; -- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-manaDecayFactorsLength)`; +- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-Mana Decay Factors Length) `; +- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-Mana Decay Factors Length)`; and - `slotPerEpoch = 2^slotsPerEpochExponent` is the number of slots in an epoch. Initially, we use @@ -389,14 +389,14 @@ Rearranging the formulas above, we have that `Potential_Mana = potentialMana0 + where - `potentialMana0 = amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent) + c * amount * manaGenerationRate * 2^(slotsPerEpochExponent - manaGenerationRateExponent) - c * amount * manaGenerationRate * -2^(slotsPerEpochExponent - manaDecayFactorsLength - manaGenerationRateExponent)`; -- `potentialManan = amount * d1 * lookupTable(n) * manaGenerationRate * 2^(-manaDecayFactorsLength-manaGenerationRateExponent)`; +2^(slotsPerEpochExponent - Mana Decay Factors Length - manaGenerationRateExponent)`; +- `potentialManan = amount * d1 * lookupTable(n) * manaGenerationRate * 2^(-Mana Decay Factors Length-manaGenerationRateExponent)`; - `potentialManan1 = -c * amount * manaGenerationRate * lookupTable(n - 1) * -2^(slotsPerEpochExponent - manaDecayFactorsLength - manaGenerationRateExponent)`. +2^(slotsPerEpochExponent - Mana Decay Factors Length - manaGenerationRateExponent)`. Analogously, we find formulas for `n < 2`: - If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * manaGenerationRate * -2^(-manaDecayFactorsLength - manaGenerationRateExponent) + amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent)`. +2^(-Mana Decay Factors Length - manaGenerationRateExponent) + amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent)`. - If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * manaGenerationRate * 2^(-manaGenerationRateExponent)`. @@ -479,7 +479,7 @@ manaGenerationRateExponent - slotsPerEpochExponent) potentialMana_n := decay(generateMana(value, d1), n) potentialMana_n_1 := decay(aux, n - 1) - potentialMana_0 := generateMana(value, d2) + aux - aux >> manaDecayFactorsLength + potentialMana_0 := generateMana(value, d2) + aux - aux >> Mana Decay Factors Length return potentialMana_n - potentialMana_n_1 + potentialMana_0 } @@ -705,8 +705,8 @@ It is highly recommended to use overflow checks for arithmetic operations when c ## Lookup Table -== TODO: If this `32` here (and above in pseudo codes) comes from `manaDecayFactorsLength`, -let's use the `manaDecayFactorsLength`?== +== TODO: If this `32` here (and above in pseudo codes) comes from `Mana Decay Factors Length`, +let's use the `Mana Decay Factors Length`?==
Mana Bits Mana Bits Count uint8 Mana Bits is the number of bits used to represent Mana. From 05b3699f6cf9c959a99c7a8472f12fdd9b82ddc7 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 09:17:44 +0100 Subject: [PATCH 079/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c8d446c2f..464473320 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -186,12 +186,6 @@ The second table describes the key parameters used for the Mana decay calculatio Mana Bits is the number of bits used to represent Mana.
Mana Bits Exponentuint8 - Mana Bits Exponent is the number of bits used to represent Mana expressed as an exponent of 2. -
Slot Duration In SecondsMana Bits Count uint8 - Mana Bits is the number of bits used to represent Mana. + Mana Bits Count is the number of bits used to represent Mana.
From 84ec8410e693844db94066776d4b85271d859c3f Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 18:02:37 +0100 Subject: [PATCH 100/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 0cf7d030e..d1f60b827 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -256,8 +256,8 @@ calculations have to be done with fixed point arithmetics. In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of -`2^Mana Decay Factors Length * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, -for different values of `n`. For the lookup Table in this document, we set `Mana Decay Factors Length = 32`, +`2^Mana Decay Factors Exponent * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, +for different values of `n`. For the lookup Table in this document, we set `Mana Decay Factors Exponent = 32`, `epochDuration = 10 * 2^slotsPerEpochExponent = 10 * 2^13` seconds (which means that the duration of an epoch in years is around `0.002597666159`), and `β = 1/3` per year. @@ -308,7 +308,7 @@ func decay(value, n) { decayFactor = lookupTable(EpochsToDecay) // apply the decay using fixed-point arithmetics. - valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, decayFactor, Mana Decay Factors Length) + valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, decayFactor, Mana Decay Factors Exponent) } // combine both uint64 variables to get the actual value @@ -358,16 +358,16 @@ consumption slots): The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the -formula for `n > 1`, noticing that we already approximated `2^Mana Decay Factors Length * exp(-β * Δ * i)` by -`lookupTable(i)`, where `Mana Decay Factors Length` is the precision of the [lookup table](#lookup-table) used. +formula for `n > 1`, noticing that we already approximated `2^Mana Decay Factors Exponent * exp(-β * Δ * i)` by +`lookupTable(i)`, where `Mana Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form `c = manaDecayFactorEpochsSum * 2^(-manaDecayFactorEpochsSumExponent)`. Given the values defined in the last section, we set `manaDecayFactorEpochsSum = TODO` and `manaDecayFactorEpochsSumExponent= TODO`. Then, `Potential_Mana = aux + aux1 + aux2`, where: - `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; -- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-Mana Decay Factors Length) `; -- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-Mana Decay Factors Length)`; +- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-Mana Decay Factors Exponent) `; +- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-Mana Decay Factors Exponent)`; and - `slotPerEpoch = 2^slotsPerEpochExponent` is the number of slots in an epoch. Initially, we use @@ -389,14 +389,14 @@ Rearranging the formulas above, we have that `Potential_Mana = potentialMana0 + where - `potentialMana0 = amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent) + c * amount * manaGenerationRate * 2^(slotsPerEpochExponent - manaGenerationRateExponent) - c * amount * manaGenerationRate * -2^(slotsPerEpochExponent - Mana Decay Factors Length - manaGenerationRateExponent)`; -- `potentialManan = amount * d1 * lookupTable(n) * manaGenerationRate * 2^(-Mana Decay Factors Length-manaGenerationRateExponent)`; +2^(slotsPerEpochExponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`; +- `potentialManan = amount * d1 * lookupTable(n) * manaGenerationRate * 2^(-Mana Decay Factors Exponent-manaGenerationRateExponent)`; - `potentialManan1 = -c * amount * manaGenerationRate * lookupTable(n - 1) * -2^(slotsPerEpochExponent - Mana Decay Factors Length - manaGenerationRateExponent)`. +2^(slotsPerEpochExponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`. Analogously, we find formulas for `n < 2`: - If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * manaGenerationRate * -2^(-Mana Decay Factors Length - manaGenerationRateExponent) + amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent)`. +2^(-Mana Decay Factors Exponent - manaGenerationRateExponent) + amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent)`. - If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * manaGenerationRate * 2^(-manaGenerationRateExponent)`. @@ -479,7 +479,7 @@ manaGenerationRateExponent - slotsPerEpochExponent) potentialMana_n := decay(generateMana(value, d1), n) potentialMana_n_1 := decay(aux, n - 1) - potentialMana_0 := generateMana(value, d2) + aux - aux >> Mana Decay Factors Length + potentialMana_0 := generateMana(value, d2) + aux - aux >> Mana Decay Factors Exponent return potentialMana_n - potentialMana_n_1 + potentialMana_0 } @@ -705,8 +705,8 @@ It is highly recommended to use overflow checks for arithmetic operations when c ## Lookup Table -== TODO: If this `32` here (and above in pseudo codes) comes from `Mana Decay Factors Length`, -let's use the `Mana Decay Factors Length`?== +== TODO: If this `32` here (and above in pseudo codes) comes from `Mana Decay Factors Exponent`, +let's use the `Mana Decay Factors Exponent`?==
Lookup Table: Decays for Mana in decay index granularity scaled to 2^32
From 2851ccd2f9b17ef714808508dba1c9f69a7dbd3b Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 18:04:08 +0100 Subject: [PATCH 101/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index d1f60b827..7062dfb4c 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -219,7 +219,7 @@ The second table describes the key parameters used for the Mana decay calculatio From 9ca0686817fb1ffa4150c78d747a7c83f62dd74c Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 18:05:33 +0100 Subject: [PATCH 102/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 7062dfb4c..5aa21e628 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -123,7 +123,7 @@ provides the specific formula for the decay function in Appendix A. Applying decay for the generation of new Mana and staking rewards is conceptually straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every -`2^slotsPerEpochExponent` slots, the epoch changes, meaning that every set of consecutive `2^slotsPerEpochExponent` +`2^Slots Per Epoch Exponent` slots, the epoch changes, meaning that every set of consecutive `2^Slots Per Epoch Exponent` slots will be in the same epoch. The decay parameter `β` (together with the Mana generation parameter) was set so the maximum theoretical Mana in @@ -184,7 +184,7 @@ The second table describes the key parameters used for the Mana decay calculatio @@ -258,7 +258,7 @@ other TIPs), as a tool to perform calculations that would otherwise be done with Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of `2^Mana Decay Factors Exponent * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, for different values of `n`. For the lookup Table in this document, we set `Mana Decay Factors Exponent = 32`, -`epochDuration = 10 * 2^slotsPerEpochExponent = 10 * 2^13` seconds (which means that the duration of an epoch in +`epochDuration = 10 * 2^Slots Per Epoch Exponent = 10 * 2^13` seconds (which means that the duration of an epoch in years is around `0.002597666159`), and `β = 1/3` per year. ### How to use the lookup table @@ -370,8 +370,8 @@ we set `manaDecayFactorEpochsSum = TODO` and `manaDecayFactorEpochsSumExponent= - `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-Mana Decay Factors Exponent)`; and -- `slotPerEpoch = 2^slotsPerEpochExponent` is the number of slots in an epoch. Initially, we use -`slotsPerEpochExponent = 13`; +- `slotPerEpoch = 2^Slots Per Epoch Exponent` is the number of slots in an epoch. Initially, we use +`Slots Per Epoch Exponent = 13`; - `d1 = slotAfterEpochi - creationSlot`; - `slotAfterEpochi` is the first slot of the epoch `i + 1`; - `d2 = consumptionSlot - firstSlotEpochJ` @@ -388,11 +388,11 @@ this, we avoid potential gameability scenarios, since all the terms added will b Rearranging the formulas above, we have that `Potential_Mana = potentialMana0 + potentialManan + potentialManan1`, where - `potentialMana0 = amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent) + c * amount * manaGenerationRate * -2^(slotsPerEpochExponent - manaGenerationRateExponent) - c * amount * manaGenerationRate * -2^(slotsPerEpochExponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`; +2^(Slots Per Epoch Exponent - manaGenerationRateExponent) - c * amount * manaGenerationRate * +2^(Slots Per Epoch Exponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`; - `potentialManan = amount * d1 * lookupTable(n) * manaGenerationRate * 2^(-Mana Decay Factors Exponent-manaGenerationRateExponent)`; - `potentialManan1 = -c * amount * manaGenerationRate * lookupTable(n - 1) * -2^(slotsPerEpochExponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`. +2^(Slots Per Epoch Exponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`. Analogously, we find formulas for `n < 2`: - If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * manaGenerationRate * @@ -470,12 +470,12 @@ and `d2 = consumptionSlot - firstSlotConsumptionEpoch`. Then, we have: // PotentialManaWithDecay calculates the generated potential mana and applies the decay to the result. func PotentialManaWithDecay(value, n, d1, d2) { if n == 0: - return generateMana(value, d1 + d2 - 2^slotsPerEpochExponent) + return generateMana(value, d1 + d2 - 2^Slots Per Epoch Exponent) else if n == 1: return decay(generateMana(value, d1), 1) + generateMana(value, d2) else: aux = MultiplicationAndShift(value * manaGenerationRate, manaDecayFactorEpochsSum, manaDecayFactorEpochsSumExponent + -manaGenerationRateExponent - slotsPerEpochExponent) +manaGenerationRateExponent - Slots Per Epoch Exponent) potentialMana_n := decay(generateMana(value, d1), n) potentialMana_n_1 := decay(aux, n - 1) From 344daba6e408b75f24f8c94cce5f9978bab250e4 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 18:07:27 +0100 Subject: [PATCH 103/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 5aa21e628..3a1135866 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -127,11 +127,11 @@ any of those cases, the node must calculate the decay based on epoch indices, no slots will be in the same epoch. The decay parameter `β` (together with the Mana generation parameter) was set so the maximum theoretical Mana in -the system is smaller than `2^manaBitsCount - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses -`manaBitsCount < 64` bits (in the case of BIC, it uses at most `manaBitsCount + 1` bits, `manaBitsCount` for the value and one -for the sign). Note that the system will almost certainly never use all the `manaBitsCount` to store Mana, since, for the Mana +the system is smaller than `2^Mana Bits Count - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses +less than 64 bits (in the case of BIC, it uses at most `Mana Bits Count + 1` bits, `Mana Bits Count` for the value and one +for the sign). Note that the system will almost certainly never use all the `Mana Bits Count` to store Mana, since, for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with Mana values -way smaller than `2^manaBitsCount - 1`; however, we must count on what would be an unreasonably large value in practice +way smaller than `2^Mana Bits Count - 1`; however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables, even if with a really small probability. ### Mana Decay Parameters @@ -377,9 +377,9 @@ and - `d2 = consumptionSlot - firstSlotEpochJ` - `firstSlotEpochJ` is the first slot of epoch `j` ; - `generationPerSlot = manaGenerationRate * 2^(-manaGenerationRateExponent)` is the Mana generated by holding 1 IOTA for -1 slot. Initially, we use `manaGenerationRate = 1` and `manaGenerationRateExponent = 80 - manaBitsCount`. This generation rate -per slot guarantees that the maximum theoretical mana in the system uses the `manaBitsCount` available bits; -- `manaBitsCount = 63`. +1 slot. Initially, we use `manaGenerationRate = 1` and `manaGenerationRateExponent = 80 - Mana Bits Count`. This generation rate +per slot guarantees that the maximum theoretical mana in the system uses the `Mana Bits Count` available bits; +- `Mana Bits Count = 63`. Note that the term `aux2` has a factor `lookupTable(n - 1) + 1` instead of `lookupTable(n - 1)` since the values in the [lookup table](#lookup-table) are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing From 0a7da715145e9a4f9a42a4b0b9e04ea3f5372b72 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 18:08:52 +0100 Subject: [PATCH 104/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 3a1135866..d1aae27f9 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -191,7 +191,7 @@ The second table describes the key parameters used for the Mana decay calculatio From c0b1b21a1ef1282a5a397e7d393f9c4b0fc5b42d Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 19:07:04 +0100 Subject: [PATCH 105/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index d1aae27f9..c01f1fae5 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -205,7 +205,7 @@ The second table describes the key parameters used for the Mana decay calculatio From 6cf1ee37c5cb7e76ec7f4372132a048e8a03052b Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 19:09:25 +0100 Subject: [PATCH 106/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c01f1fae5..1f01a8bf3 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -284,11 +284,11 @@ below. First, we define three auxiliary functions: - The function returns `valueHi, valueLo`, which represent the 32 upper bits and the 32 lower bits (respectively) of the desired result. With the functions above defined, we proceed to define the `decay` function that takes as input a `uint64` -value `value` and decays it by the correct decay factor relative to `n` epochs. +value `value` and decays it by the correct decay factor relative to `epochIndexDiff` epochs. ```go -func decay(value, n) { - if value == 0 or n == 0 { +func decay(value, epochIndexDiff) { + if value == 0 or epochIndexDiff == 0 { return value } @@ -296,8 +296,8 @@ func decay(value, n) { valueHi = upperBits(value, 32) valueLo = lowerBits(value, 32) - // we keep applying the lookup table factors as long as n epochs are left - remainingEpochs = n + // we keep applying the lookup table factors as long as epochIndexDiff epochs are left + remainingEpochs = epochIndexDiff while remainingEpochs > 0 { EpochsToDecay = remainingEpochs if EpochsToDecay > 365 { From fa2e2fb7162a99a143ca50b84754fd478de1655a Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Wed, 27 Sep 2023 19:25:03 +0100 Subject: [PATCH 107/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 1f01a8bf3..f794abd75 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -286,7 +286,13 @@ below. First, we define three auxiliary functions: With the functions above defined, we proceed to define the `decay` function that takes as input a `uint64` value `value` and decays it by the correct decay factor relative to `epochIndexDiff` epochs. -```go +`decay(value, epochIndexDiff)`: +- If `value == 0` or `epochIndexDiff==0`, return `value`. +- Else, let `valueHi = upperBits(value, 32)` and `valueLo = lowerBits(value, 32)` +- Let `m` and `n` be natural numbers such that `m + n* Mana Decay Factors Length = epochIndexDiff`, and `m Date: Wed, 27 Sep 2023 19:26:48 +0100 Subject: [PATCH 108/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 43 ++++++++------------------------------- 1 file changed, 8 insertions(+), 35 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index f794abd75..bd4bc3b62 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -281,46 +281,19 @@ below. First, we define three auxiliary functions: valueHi = (valueHi >> shiftFactor) + upperBits(valueLo, 32) valueLo = lowerBits(valueLo, 32) ``` - - The function returns `valueHi, valueLo`, which represent the 32 upper bits and the 32 lower bits (respectively) of the desired result. + - The function returns `valueHi, valueLo`, representing the 32 upper bits and the 32 lower bits (respectively) of the desired result. With the functions above defined, we proceed to define the `decay` function that takes as input a `uint64` value `value` and decays it by the correct decay factor relative to `epochIndexDiff` epochs. `decay(value, epochIndexDiff)`: - If `value == 0` or `epochIndexDiff==0`, return `value`. -- Else, let `valueHi = upperBits(value, 32)` and `valueLo = lowerBits(value, 32)` -- Let `m` and `n` be natural numbers such that `m + n* Mana Decay Factors Length = epochIndexDiff`, and `m 0 { - EpochsToDecay = remainingEpochs - if EpochsToDecay > 365 { - EpochsToDecay = 365 - } - remainingEpochs -= EpochsToDecay - - decayFactor = lookupTable(EpochsToDecay) - - // apply the decay using fixed-point arithmetics. - valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, decayFactor, Mana Decay Factors Exponent) - } - - // combine both uint64 variables to get the actual value - return valueHi << 32 + valueLo -} -``` +- Else: + - Let `valueHi = upperBits(value, 32)` and `valueLo = lowerBits(value, 32)`. + - Let `m` and `n` be natural numbers such that `m + n* Mana Decay Factors Length = epochIndexDiff`, and `m Date: Wed, 27 Sep 2023 19:31:25 +0100 Subject: [PATCH 109/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index bd4bc3b62..2f6cede02 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -264,7 +264,7 @@ years is around `0.002597666159`), and `β = 1/3` per year. ### How to use the lookup table In this section, we define a function `decay(value, n)`, that decays an amount of Mana `value` by the factor -relative to `n` epochs. Note that the table defined above only gives the values of `lookupTable(n)` for some i +relative to `n` epochs. Note that the table defined above only gives the values of `Mana Decay Factors(n)` for some i values of `n` up to `365`. To calculate `decay(value, n)` for larger values of `n`, we combine values defined in the [lookup table](#lookup-table) for other numbers smaller than `365`, using an algorithm that will be defined below. First, we define three auxiliary functions: @@ -291,8 +291,8 @@ value `value` and decays it by the correct decay factor relative to `epochIndexD - Else: - Let `valueHi = upperBits(value, 32)` and `valueLo = lowerBits(value, 32)`. - Let `m` and `n` be natural numbers such that `m + n* Mana Decay Factors Length = epochIndexDiff`, and `m 1`, noticing that we already approximated `2^Mana Decay Factors Exponent * exp(-β * Δ * i)` by -`lookupTable(i)`, where `Mana Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. +`Mana Decay Factors(i-1)`, where `Mana Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form `c = manaDecayFactorEpochsSum * 2^(-manaDecayFactorEpochsSumExponent)`. Given the values defined in the last section, we set `manaDecayFactorEpochsSum = TODO` and `manaDecayFactorEpochsSumExponent= TODO`. Then, `Potential_Mana = aux + aux1 + aux2`, where: - `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; -- `aux1 = amount * generationPerSlot * d1 * lookupTable(n) * 2^(-Mana Decay Factors Exponent) `; -- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (lookupTable(n - 1) + 1) * 2^(-Mana Decay Factors Exponent)`; +- `aux1 = amount * generationPerSlot * d1 * Mana Decay Factors(n-1) * 2^(-Mana Decay Factors Exponent) `; +- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (Mana Decay Factors(n - 2) + 1) * 2^(-Mana Decay Factors Exponent)`; and - `slotPerEpoch = 2^Slots Per Epoch Exponent` is the number of slots in an epoch. Initially, we use @@ -360,7 +360,7 @@ and per slot guarantees that the maximum theoretical mana in the system uses the `Mana Bits Count` available bits; - `Mana Bits Count = 63`. -Note that the term `aux2` has a factor `lookupTable(n - 1) + 1` instead of `lookupTable(n - 1)` since the values +Note that the term `aux2` has a factor `Mana Decay Factors(n - 2) + 1` instead of `Mana Decay Factors(n - 2)` since the values in the [lookup table](#lookup-table) are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing this, we avoid potential gameability scenarios, since all the terms added will be rounded down in the formula. @@ -369,12 +369,12 @@ where - `potentialMana0 = amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent) + c * amount * manaGenerationRate * 2^(Slots Per Epoch Exponent - manaGenerationRateExponent) - c * amount * manaGenerationRate * 2^(Slots Per Epoch Exponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`; -- `potentialManan = amount * d1 * lookupTable(n) * manaGenerationRate * 2^(-Mana Decay Factors Exponent-manaGenerationRateExponent)`; -- `potentialManan1 = -c * amount * manaGenerationRate * lookupTable(n - 1) * +- `potentialManan = amount * d1 * Mana Decay Factors(n-1) * manaGenerationRate * 2^(-Mana Decay Factors Exponent-manaGenerationRateExponent)`; +- `potentialManan1 = -c * amount * manaGenerationRate * Mana Decay Factors(n - 2) * 2^(Slots Per Epoch Exponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`. Analogously, we find formulas for `n < 2`: -- If `n = 1`: `Potential_Mana = amount * d1 * lookupTable(1) * manaGenerationRate * +- If `n = 1`: `Potential_Mana = amount * d1 * Mana Decay Factors(0) * manaGenerationRate * 2^(-Mana Decay Factors Exponent - manaGenerationRateExponent) + amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent)`. - If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * manaGenerationRate * 2^(-manaGenerationRateExponent)`. From 5b5f3828918fc33241a6134f34e4215928032c35 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Fri, 29 Sep 2023 21:41:22 +0100 Subject: [PATCH 110/157] Add files via upload --- tips/TIP-0039/img/slots_potential_mana-2.png | Bin 0 -> 23283 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tips/TIP-0039/img/slots_potential_mana-2.png diff --git a/tips/TIP-0039/img/slots_potential_mana-2.png b/tips/TIP-0039/img/slots_potential_mana-2.png new file mode 100644 index 0000000000000000000000000000000000000000..30772b644c110353bd56277a2f94053824b7b1f8 GIT binary patch literal 23283 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 literal 0 HcmV?d00001 From cf229b708f3305f1cf1e4e93806fad53def7a51f Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Fri, 29 Sep 2023 21:42:37 +0100 Subject: [PATCH 111/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 2f6cede02..e216192a3 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -315,7 +315,7 @@ We model the potential Mana generated by an output holding `S` IOTA coins as the per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time an epoch ends, where `Δ` i is the epoch duration. -![](./img/slots_potential_mana.png) +![](./img/slots_potential_mana-2.png) Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n = j - i`, and for the sake of the explanation, assume `n > 1`. All the Mana generated in epoch `i` "crosses" `n` decay boundaries; From 9f355cbbaa5e01d087187035fcac88e0e2103449 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sat, 30 Sep 2023 18:35:49 +0100 Subject: [PATCH 112/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 106 ++++++-------------------------------- 1 file changed, 16 insertions(+), 90 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index e216192a3..72ce912d9 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -81,7 +81,8 @@ It is an essential element of the IOTA protocol, as it is used: ## Mana Burn -The **Mana holdings** of a user is the sum of all the Potential Mana and Stored Mana (but not the Mana Rewards) in their Account Output which they use to issue blocks. According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a +The **Mana holdings** of a user are the sum of all the Potential Mana and Stored Mana (but not the Mana Rewards) in their Account Output +that they use to issue blocks. According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a certain amount of Mana dictated by the work score of the block and the Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Users who overspend Mana (i.e., try to issue more blocks than their Mana Holdings allow) will have their account locked until their debt is paid. @@ -117,26 +118,27 @@ to be applied to all forms of Mana: - Mana rewarded for staking and delegation ([Mana rewards](#mana-rewards)). As the exact formulas in which the decay factor will be applied might differ among the Mana types, it is essential to point -out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper +out that all of them are based on the same exponential decay with the same parameter β. The Incentives Whitepaper provides the specific formula for the decay function in Appendix A. Applying decay for the generation of new Mana and staking rewards is conceptually straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every -`2^Slots Per Epoch Exponent` slots, the epoch changes, meaning that every set of consecutive `2^Slots Per Epoch Exponent` +2`Slots Per Epoch Exponent` slots, the epoch changes, meaning that every set of consecutive 2`Slots Per Epoch Exponent` slots will be in the same epoch. -The decay parameter `β` (together with the Mana generation parameter) was set so the maximum theoretical Mana in -the system is smaller than `2^Mana Bits Count - 1`. This means that, even though Mana is stored as a `uint64`, it effectively uses -less than 64 bits (in the case of BIC, it uses at most `Mana Bits Count + 1` bits, `Mana Bits Count` for the value and one -for the sign). Note that the system will almost certainly never use all the `Mana Bits Count` to store Mana, since, for the Mana +The decay parameter β (together with the Mana generation parameter) was set so the maximum theoretical Mana in +the system is smaller than 2`Bits Count`-1. This means that, even though Mana is stored as a uint64, it effectively uses +less than 64 bits (in the case of BIC, it uses at most `Bits Count`+1 bits, `Bits Count` for the value and one +for the sign). Note that the system will almost certainly never use all the `Bits Count` to store Mana since, for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with Mana values -way smaller than `2^Mana Bits Count - 1`; however, we must count on what would be an unreasonably large value in practice -to avoid overflowing of the variables, even if with a really small probability. +way smaller than 2`Bits Count`-1; however, we must count on what would be an unreasonably large value in practice +to avoid overflowing of the variables even if with a minimal probability. ### Mana Decay Parameters -The tables below describe the key parameters used for the Mana decay calculations in the next sections of this TIP. Notice that the parameters in the first table are only used in the explanations in this TIP, but not in the code. +The tables below describe the key parameters used for the Mana decay calculations in the next sections of this TIP. Notice that +the parameters in the first table are only used in the explanations in this TIP, but not in the code.
Lookup Table: Decays for Mana in decay index granularity scaled to 2^32
Mana Decay Factors Exponent uint8 - Mana Decay Factors Exponent is the scaling of ManaDecayFactors expressed as an exponent of 2. + Mana Decay Factors Exponent is the scaling of Mana Decay Factors expressed as an exponent of 2.
Slots Per Epoch Exponent uint8 - Slots Per Epoch Exponent is the number of slots in an epoch expressed as an exponent of 2. (2**SlotsPerEpochExponent) == slots in an epoch. + Slots Per Epoch Exponent is the number of slots in an epoch expressed as an exponent of 2. (2**Slots Per Epoch Exponent) == slots in an epoch.
Mana Generation Rate uint8 - Mana Generation Rate is the amount of potential Mana generated by 1 IOTA in 1 slot. + Mana Generation Rate is the amount of potential Mana generated by 1 IOTA in 1 slot, when multiplied by `2^Mana Generation Rate Exponent`.
Mana Decay Factors Length uint16 - The length of Mana Decay Factors. + The length of Mana Decay Factors lookup table.
@@ -156,91 +158,15 @@ The tables below describe the key parameters used for the Mana decay calculation - + -
Epoch DurationΔ - The duration of an epoch in seconds. + The duration of an epoch in years.
- -The second table describes the key parameters used for the Mana decay calculations in the next sections of this TIP, as they are used in the code. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Mana Bits Countuint8 - Mana Bits Count is the number of bits used to represent Mana. -
Slot Duration In Secondsuint8 - Slot Duration In Seconds defines the duration of each slot in seconds. -
Slots Per Epoch Exponentuint8 - Slots Per Epoch Exponent is the number of slots in an epoch expressed as an exponent of 2. (2**Slots Per Epoch Exponent) == slots in an epoch. -
Mana Generation Rateuint8 - Mana Generation Rate is the amount of potential Mana generated by 1 IOTA in 1 slot, when multiplied by `2^Mana Generation Rate Exponent`. -
Mana Generation Rate Exponentuint8 - Mana Generation Rate Exponent is the scaling of Mana Generation Rate expressed as an exponent of 2. -
Mana Decay Factors Lengthuint16 - The length of Mana Decay Factors lookup table. -
Mana Decay Factorsuint32Array - Mana Decay Factors is a lookup table of epoch index diff to mana decay factor (slice index 0 = 1 epoch). -
Mana Decay Factors Exponentuint8 - Mana Decay Factors Exponent is the scaling of Mana Decay Factors expressed as an exponent of 2. -
Mana Decay Factor Epochs Sumuint32 - Mana Decay Factor Epochs Sum is an integer approximation of the sum of decay over epochs. -
Mana Decay Factor Epochs Sum Exponentuint8 - Mana Decay Factor Epochs Sum Exponent is the scaling of Mana Decay Factor Epochs Sum expressed as an exponent of 2. -
- - - +Additionally, we use the protocol parameters, as defined in [TIP-49](../TIP-0049/tip-0049.md), and `Decay Factors Length`, +defined as the length of the lookup Table `Decay Factors`. ## Mana and fixed point arithmetics From 82c348b8c4d588f04749d099d49248267977719c Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sat, 30 Sep 2023 18:37:20 +0100 Subject: [PATCH 113/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 72ce912d9..1ae8561eb 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -175,17 +175,16 @@ rounding behaviors in different architectures. The results of the operations inv differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, for example); however, differences that would be considered negligible by those modules can be fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviors in the -system. For that reason, fixed point arithmetics (which does not expose the nodes to these rounding divergencies) +system. For that reason, fixed point arithmetics (which do not expose the nodes to these rounding divergencies) must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of -`2^Mana Decay Factors Exponent * exp(-β * epochDuration * n)`, where `β` and `epochDuration` are protocol parameters, -for different values of `n`. For the lookup Table in this document, we set `Mana Decay Factors Exponent = 32`, -`epochDuration = 10 * 2^Slots Per Epoch Exponent = 10 * 2^13` seconds (which means that the duration of an epoch in -years is around `0.002597666159`), and `β = 1/3` per year. +2`Decay Factors Exponent`exp(-βΔn), for different values of `n` ranging from 1 to `Decay Factors Length`. +For the lookup Table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, +`Slot Duration in Seconds` = 10, (which implies that Δ = 0.002597666159), and β = 1/3 per year. ### How to use the lookup table From a5d80c8b8f076f7670d30666337dbd13c39a525d Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sat, 30 Sep 2023 19:17:42 +0100 Subject: [PATCH 114/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 1ae8561eb..c08eb8d5a 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -188,16 +188,18 @@ For the lookup Table in this document, we set `Decay Factors Exponent` = 32, `Sl ### How to use the lookup table -In this section, we define a function `decay(value, n)`, that decays an amount of Mana `value` by the factor -relative to `n` epochs. Note that the table defined above only gives the values of `Mana Decay Factors(n)` for some i -values of `n` up to `365`. To calculate `decay(value, n)` for larger values of `n`, we combine -values defined in the [lookup table](#lookup-table) for other numbers smaller than `365`, using an algorithm that will be defined -below. First, we define three auxiliary functions: - -- `upperBits(value, n)`: given a `uint64` integer `value`, returns its upper `n` bits -- `lowerBits(value, n)`: given a `uint64` integer `value`, returns its lower `n` bits -- `MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the result of a multiplication of a `uint64` by a `uint32`, shifted `shiftFactor` times to the right, whenever this result is smaller than `2^64`. To do so, it uses the following algorithm: - - Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than `2^64`, `multFactor` be an integer smaller than `2^32`, and `shiftFactor` be an integer between 0 and 32. +In this section, we define a function `decay(value, epochIndexDiff)`, that decays an amount of Mana `value` by the +factor relative to `epochIndexDiff` epochs. Note that the table `Decay Factors` defined above only gives the values +of decays factors for up to `Decay Factors Length` epochs. To calculate the decay for larger periods of time, we combine +values defined in the [lookup table](#lookup-table) for other numbers smaller than `Decay Factors Length`, using an +algorithm that will be defined below. First, we define three auxiliary functions: + +- `upperBits(value, n)`: given a uint64 integer `value`, returns its upper `n` bits +- `lowerBits(value, n)`: given a uint64 integer `value`, returns its lower `n` bits +- `MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the result +- of a multiplication of a uint64 by a uint32, shifted `shiftFactor` times to the right, whenever this result is smaller +- than 264. To do so, it uses the following algorithm: + - Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than 264, `multFactor` be an integer smaller than 232, and `shiftFactor` be an integer between 0 and 32. - Let `>>` be a right shift (thus, `>>n` means shifting to the right `n` times). Analogously, let `<<` be a left shift. - Then, apply: ``` @@ -208,16 +210,18 @@ below. First, we define three auxiliary functions: ``` - The function returns `valueHi, valueLo`, representing the 32 upper bits and the 32 lower bits (respectively) of the desired result. -With the functions above defined, we proceed to define the `decay` function that takes as input a `uint64` -value `value` and decays it by the correct decay factor relative to `epochIndexDiff` epochs. +With the functions above defined, we proceed to define the `decay` function that takes as input a uint64 value `value` +and decays it by the correct decay factor relative to `epochIndexDiff` epochs. OBS: note that here, `Decay Factors(epochIndexDiff)` +denotes the value of the table relative to `epochIndexDiff` epochs, which not necessarily corresponds to the `epochIndexDiff`th +entry of the table `decay(value, epochIndexDiff)`: - If `value == 0` or `epochIndexDiff==0`, return `value`. - Else: - Let `valueHi = upperBits(value, 32)` and `valueLo = lowerBits(value, 32)`. - - Let `m` and `n` be natural numbers such that `m + n* Mana Decay Factors Length = epochIndexDiff`, and `m Date: Sat, 30 Sep 2023 19:38:22 +0100 Subject: [PATCH 115/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c08eb8d5a..f76b35454 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -241,27 +241,25 @@ derived from the UTXO ledger, based on the UTXO IOTA coin value and the time it ### Rationale behind the Potential Mana formulas -We model the potential Mana generated by an output holding `S` IOTA coins as the combination of a fixed generation -per slot `γ * S` and a decay equivalent to a multiplication by `exp(-β * Δ)` every time an epoch ends, where `Δ` i -is the epoch duration. +We model the potential Mana generated by an output holding S IOTA coins as the combination of a fixed generation +per slot γS and a decay equivalent to a multiplication by exp(-βΔ) every time an epoch ends. ![](./img/slots_potential_mana-2.png) -Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n = j - i`, and for -the sake of the explanation, assume `n > 1`. All the Mana generated in epoch `i` "crosses" `n` decay boundaries; -thus, it must be decayed `n` times. The Mana generated in epoch `i + 1` "crosses" `n - 1` decay boundaries, so it -must be decayed `n - 1` times, and so on, until the Mana generated in epoch `j`, which is not decayed at all. -Adding these values, we find the following formulas (where `d` is the number of slots in an epoch): - -`Potential Mana = γ * S * [d1 * exp(-β * Δ * n) + d * exp(-β * Δ * (n - 1)) + d * exp(-β * Δ * (n - 2)) + ... + -d * exp(-β * Δ) + d2] = γ * S * d1 * exp(-β * Δ * n) + γ * S * d2 + sum(γ * S * d * exp(-β * Δ * i)) = -γ * S * [d1 * exp(-β * Δ * n) + d2 + d * exp(-β * Δ) * (1 - exp(-β * Δ * (n - 1))) / (1 - exp(-β * Δ))]`, -where the summation is over `i = 1, ..., n - 1`. - -Analogously, if `n ≤ 1`, we find the following results (here `δ` is the difference between the creation and -consumption slots): -- If `n = 1`: `Potential Mana = γ * S * d1 * exp(-β * Δ) + γ * S * d2`. -- If `n = 0`: `Potential Mana = γ * S * δ`. +Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let n=`j`-`i`, and for +the sake of the explanation, assume n>1. All the Mana generated in epoch `i` "crosses" n decay boundaries; +thus, it must be decayed n times. The Mana generated in epoch `i`+1 "crosses" n-1 decay boundaries, so it +must be decayed n-1 times, and so on, until the Mana generated in epoch `j`, which is not decayed at all. +Adding these values, we find the following formulas (where d is the number of slots in an epoch): + +Potential Mana = γSd1 exp(-βΔn) + ΣγSd exp(-βΔi) + γSd2, where the summation is over i = 1,...,n-1. + +Solving the sum, this results: + +Potential Mana = γSd1 exp(-βΔn) + γSd2 + γSd exp(-βΔ) (1 - exp(-βΔ(n-1))) / (1-exp(-βΔ)), + +Analogously, if n=1, Potential Mana = γSd1 exp(-βΔ) + γSd2; if n=0, Potential Mana = γSδ, +where δ is the difference between the creation and consumption slots. ### Potential Mana formulas with fixed point arithmetics From 830512d2331e11450df37145fc65d4c4320ba269 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sat, 30 Sep 2023 19:39:23 +0100 Subject: [PATCH 116/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index f76b35454..d4dcab263 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -227,10 +227,10 @@ entry of the table Other implementations of the functions above are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and multiplications with integers might lead to different results when the order is altered. -Example: suppose one needs to calculate `1002 * 99 / 100 *21 / 100`. Following the left-to-right order, this -would result in `1002 * 99 / 100 * 21 / 100 = 99198 / 100 * 21 / 100 = 991 * 21 / 100 = 20811 / 100 = 208`. -If someone did this operation in a different order, let's say `1002 * 21 / 100 * 99 / 100`, the result would be -`1002 * 21 / 100 * 99 / 100 = 21042 / 100 * 99 / 100 = 210 * 99 / 100 = 20790 / 100 = 207`. +Example: suppose one needs to calculate 1002 * 99 / 100 *21 / 100. Following the left-to-right order, this +would result in 1002 * 99 / 100 * 21 / 100 = 99198 / 100 * 21 / 100 = 991 * 21 / 100 = 20811 / 100 = 208. +If someone did this operation in a different order, let's say 1002 * 21 / 100 * 99 / 100, the result would be +1002 * 21 / 100 * 99 / 100 = 21042 / 100 * 99 / 100 = 210 * 99 / 100 = 20790 / 100 = 207. ## Potential Mana From 0ca8eaaadebfa34bc6433b9104d06d2b4264a725 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sat, 30 Sep 2023 19:51:32 +0100 Subject: [PATCH 117/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index d4dcab263..ee3d3663c 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -616,7 +616,7 @@ It is highly recommended to use overflow checks for arithmetic operations when c let's use the `Mana Decay Factors Exponent`?== - + From 2e954c3e068d061bbdbfbec57c18fa949dc4fd9b Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Sun, 1 Oct 2023 09:59:04 +0200 Subject: [PATCH 118/157] Throw out outdated BIC descriptions --- .../{gFLB1Ms.png => data_flow_overview.png} | Bin tips/TIP-0039/tip-0039.md | 85 ++++-------------- 2 files changed, 17 insertions(+), 68 deletions(-) rename tips/TIP-0039/img/{gFLB1Ms.png => data_flow_overview.png} (100%) diff --git a/tips/TIP-0039/img/gFLB1Ms.png b/tips/TIP-0039/img/data_flow_overview.png similarity index 100% rename from tips/TIP-0039/img/gFLB1Ms.png rename to tips/TIP-0039/img/data_flow_overview.png diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index ee3d3663c..1c59b612f 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -403,21 +403,12 @@ market development. All output types, except Foundry and Delegation Outputs, can hold stored Mana in the *Mana* field. This field represents the amount of stored Mana at the output's creation time until the time when the output is consumed without decay applied to it. +Decay must therefore be applied whenever an output containing Stored Mana is consumed. The creation slot of each output with stored Mana. + ### Stored Mana Semantic Validation -- Each output that contains stored Mana must also contain IOTA coins due to storage deposit requirements. -- Stored Mana must be soulbound to an account. -- Because stored Mana lives on UTXOs and is consumed by transactions, it cannot be spent within a block. It must -be allotted to an account's BIC in order to pay for Mana burned by blocks. -- *Mana Sales Outputs* must be used for transferring stored or potential Mana freely from one account to another. -- It is possible to transfer stored Mana without transferring IOTA coins or the potential Mana generated from -those tokens. -- The decay must be applied to stored Mana whenever the output containing that stored Mana is consumed. -- To calculate the decay of stored Mana, the creation time of each output with stored Mana must be contained in -transactions. -- The amount of stored Mana must be decayed before stored Mana is transferred into a new output as follows: +- Stored Mana must be decayed before it is transferred into a new output as follows: - Let `manaAmount`, `consumptionSlot`, and `creationSlot`, be -
Lookup Table: Decays for Mana in decay index granularity scaled to 2^32Lookup Table: Decays for Mana in decay index granularity scaled to 232
n Type
@@ -466,57 +457,26 @@ neighbors based on Mana burned from the block issuance credits by the block. It between **blocks** and **transactions**: congestion control only deals with blocks, which are the containers that carry transactions around the network. It does not care about the transactions inside the blocks. The example below shows a ledger with a conflicting branch (perhaps due to a double spend), so only one branch -(either the set of red or the set of green transactions) can ultimately modify the ledger (UTXOs consumed), not both. +(either the set of red or the set of green transactions) can ultimately modify the ledger, not both. However, all these blocks must be gossiped, whether they contain red or green transactions. Thus, they must pay for the BIC used to get through schedulers regardless of whether the transaction within modifies the ledger. This is -why Mana cannot be burned from BIC by a transaction; it can only be burned by a block. +why BIC cannot be burned by a transaction - it can only be burned by a block. + +![](./img/data_flow_overview.png) -![](./img/gFLB1Ms.png) +Because a block cannot modify the UTXO ledger but the Mana the block burns must be deducted from the account's BIC balance, the BIC is stored in an accounts ledger. This ledger is a map from an Account ID to block issuer data, which includes the BIC balance, the block issuer keys and when the Block Issuer Feature expires among other data. This separate ledger is partly derived from the Block Issuer Feature in an account in the UTXO ledger. The BIC balance of an account can only be modified in two ways: +- BIC is subtracted from the ledger when the corresponding account issues a block signed by one of its Block Issuer Keys. +- BIC is increased in the ledger when a transaction allots Mana to that account. + +Updates to the BIC balance happen upon slot commitments. Mana Decay is applied to the BIC for the +accounts whose BIC was changed in that slot. ### Block Issuance Credit Semantic Validation -- Block issuance credits must be stored on a per-account basis. -- Accounts must be represented by _Account Outputs_ on the UTXO ledger. The cost of permanently storing any outputs -(until destruction) in the ledger is covered by the _storage deposit_. Because of that, the number of accounts is -capped at a number proportional to the max supply of tokens, contrary to the number of plain addresses. Because -BIC must be tracked in slot commitments, keeping the number of entries (even though the user can create multiple -accounts) in that data structure as small as possible is desirable. Using account IDs for that purpose is thus a -good fit. -- It is not possible to store BIC without an Account Output because Mana burned by blocks must also be deducted -from BIC, and the block cannot modify the Account Output. Consequently, the ledger state is not bloated by having -to keep track of block issuance credits because there is a corresponding account output in the UTXO ledger that -requires a storage deposit in IOTA coins. Thus, the dust protection mechanism used for the UTXO ledger also -indirectly prevents dust from accumulating in tracking the block issuance credits. -- A commitment and time division mechanism is required for BIC dynamics: current slot commitments present in IOTA 2.0. - - The end time of an epoch is used for the decay calculations. - - Definition of slots based on the time of the genesis slot and slot duration. - - A commitment mechanism per slot is needed to ensure the unified perception of the BIC in the longer run. -- A global agreement on the BIC balances among all the nodes is required. - - It can be achieved by including the BIC vector in the slot commitments. This guarantees that all nodes have -the same perception of the BIC balances from a certain point in time. -- If a block is orphaned, the block will not be included in a commitment, and hence, the balance of BIC of the -account that issued the block must be unaffected by that block. -- The time of the slot commitment must be used to align the local version of the BIC vector with the objective, -committed version. It allows for the global control of the BIC dynamic with a Mana decay function. - - This decrease is also applied to the potential and stored Mana (that can be allotted to the account as BIC) -so users cannot gain by delaying or advancing the allotting. -- The balance of the BIC vector at the slot commitment must be the sum of: - - The balances of the previously committed BIC vector. - - All Mana allotted as BIC in accepted transactions of the committed slot. Note that, in theory, in the case of -only decaying the BIC vector at the end of each epoch, this Mana would have to be decayed by a factor proportional -to the difference between the transaction slot index and the index of the last slot of the epoch. However, since the -decay rate is small, this difference will always be smaller than half a percent. We understand that this difference -(since it is not composable and can only be "taken profit of" once) does not justify the user experience-related -issues (like having to allot more than 1 Mana to being able to burn 1 Mana in the same transaction) and -implementation complications of applying this small decay. Thus, we allot as a BIC the total value of Mana being -allotted in a transaction. - - Subtract from BIC all Mana burned by accepted blocks of the committed slots. -- BIC updates (increase and or deduction/Mana burning) must happen upon slot commitments. BIC decays happen at the -end of each epoch. -- Mana decay must be applied at the end of the epoch according to the algorithm: - - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`, which is the last slot of an epoch. -This means that all additions of allotted BIC and Mana burnt relative to slot `i` were already done. We must now -decay the remaining value of BIC by applying: +- When applying Mana Decay to BIC at the end of a slot, it must be applied as follows: + - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`. Since all additions of allotted BIC were already decayed in that slot, only the previous value of BIC must be decayed, relative to the last slot it was decayed in, by applying: + +TODO: This function is weird, it doesn't take into account the last time the BIC was decayed and the current time. ```go if BIC > 0: @@ -524,17 +484,6 @@ if BIC > 0: else: new_BIC = BIC ``` - -If `i` is not the last slot of the epoch, this decay should not be applied. -- A block must include the permission of an account from which Mana will be burned from BIC to pay for the block. - - A block must contain an account's permission (i.e., a digital signature) that nodes can use to verify that -the account has authorized the block and that Mana can be burned from the BIC of that account. -- The issuer must specify the maximum amount of Mana they will allow to be burned from BIC. - - In the above-mentioned permission, the account owner must commit to a certain maximum amount of Mana that -will be burned from BIC. -- The declared burning amount must be at least the required burning for the current slot. - - The required burning amount for a block is calculated with the Reference Mana Cost (RMC), which depends on -the past network activity and gets updated every slot. ## Mana rewards From c688fa95b3ee93c7dc2d8a7414cfab6b0effd938 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Sun, 1 Oct 2023 12:25:59 +0200 Subject: [PATCH 119/157] Polish Potential & Stored Mana section --- tips/TIP-0039/tip-0039.md | 99 ++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 58 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 1c59b612f..fda0b215b 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -103,36 +103,32 @@ becomes too large for the majority of users, and activity drops. The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid price manipulations by malicious actors. Note that blocks from issuers with negative BIC balances are excluded with respect to the RMC calculation, but they do make part of the slot commitment. To limit fluctuations in the RMC, -it is proposed to update its value every MCA slot at least. +it is recommended to update its value every MCA slot at least. ## Mana Decay -Mana decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana +Mana Decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation both from IOTA coins and the staking mechanism, which will be discussed in detail in the next sections. To guarantee non-gameability (e.g., splitting accounts or other behaviors that are not helpful for the system -well-functioning cannot be profitable for the user) and the fairness of Mana, the same global decay factor needs -to be applied to all forms of Mana: -- newly generated Mana ([Potential Mana](#potential-mana)); -- Mana stored in UTXOs ([Stored Mana](#stored-mana)); -- Mana bound to accounts for block issuance ([Block Issuance Credit](#block-issuance-credit)); -- Mana rewarded for staking and delegation ([Mana rewards](#mana-rewards)). +well-functioning) and the fairness of Mana, the same global decay factor needs +to be applied to all the above-mentioned forms of Mana. As the exact formulas in which the decay factor will be applied might differ among the Mana types, it is essential to point -out that all of them are based on the same exponential decay with the same parameter β. The Incentives Whitepaper +out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper (TODO: Link) provides the specific formula for the decay function in Appendix A. Applying decay for the generation of new Mana and staking rewards is conceptually straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every -2`Slots Per Epoch Exponent` slots, the epoch changes, meaning that every set of consecutive 2`Slots Per Epoch Exponent` +2Slots Per Epoch Exponent slots, the epoch changes, meaning that every set of consecutive 2Slots Per Epoch Exponent slots will be in the same epoch. -The decay parameter β (together with the Mana generation parameter) was set so the maximum theoretical Mana in -the system is smaller than 2`Bits Count`-1. This means that, even though Mana is stored as a uint64, it effectively uses -less than 64 bits (in the case of BIC, it uses at most `Bits Count`+1 bits, `Bits Count` for the value and one +The decay parameter `β` (together with the Mana generation parameter `Mana Structure::Generation Rate`) was set so the maximum theoretical Mana in +the system is smaller than 2Bits Count - 1, where `Bits Count` refers to the `Mana Structure::Bits Count` protocol parameter. This means that, even though Mana is stored as a uint64, it effectively uses +less than 64 bits (in the case of BIC, it uses at most `Bits Count + 1` bits, `Bits Count` for the value and one for the sign). Note that the system will almost certainly never use all the `Bits Count` to store Mana since, for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with Mana values -way smaller than 2`Bits Count`-1; however, we must count on what would be an unreasonably large value in practice +way smaller than 2Bits Count - 1; however, we must count on what would be an unreasonably large value in practice to avoid overflowing of the variables even if with a minimal probability. ### Mana Decay Parameters @@ -146,26 +142,26 @@ the parameters in the first table are only used in the explanations in this TIP, - + - + - +
NameDescription
ββ Global exponential decay parameter.
γγ Defines fixed potential Mana generation per slot.
ΔΔ The duration of an epoch in years.
-Additionally, we use the protocol parameters, as defined in [TIP-49](../TIP-0049/tip-0049.md), and `Decay Factors Length`, +Additionally, we use the protocol parameters, as defined in [TIP-49], and `Decay Factors Length`, defined as the length of the lookup Table `Decay Factors`. ## Mana and fixed point arithmetics @@ -182,9 +178,9 @@ calculations have to be done with fixed point arithmetics. In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of -2`Decay Factors Exponent`exp(-βΔn), for different values of `n` ranging from 1 to `Decay Factors Length`. -For the lookup Table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, -`Slot Duration in Seconds` = 10, (which implies that Δ = 0.002597666159), and β = 1/3 per year. +2Decay Factors Exponentexp(-βΔn), for different values of `n` ranging from 1 to `Decay Factors Length`. +For the lookup table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, +`Slot Duration in Seconds` = 10, (which implies that `Δ = 0.002597666159`), and `β = 1/3` per year. ### How to use the lookup table @@ -194,35 +190,31 @@ of decays factors for up to `Decay Factors Length` epochs. To calculate the deca values defined in the [lookup table](#lookup-table) for other numbers smaller than `Decay Factors Length`, using an algorithm that will be defined below. First, we define three auxiliary functions: -- `upperBits(value, n)`: given a uint64 integer `value`, returns its upper `n` bits -- `lowerBits(value, n)`: given a uint64 integer `value`, returns its lower `n` bits +- Let `upperBits(value, n)` be: given a uint64 integer `value`, returns its upper `n` bits +- Let `lowerBits(value, n)` be: given a uint64 integer `value`, returns its lower `n` bits - `MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the result - of a multiplication of a uint64 by a uint32, shifted `shiftFactor` times to the right, whenever this result is smaller -- than 264. To do so, it uses the following algorithm: - - Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than 264, `multFactor` be an integer smaller than 232, and `shiftFactor` be an integer between 0 and 32. +- than 264. To do so, it uses the following algorithm: + - Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than 264, `multFactor` be an integer smaller than 232, and `shiftFactor` be an integer between 0 and 32. - Let `>>` be a right shift (thus, `>>n` means shifting to the right `n` times). Analogously, let `<<` be a left shift. - - Then, apply: - ``` - valueHi = valueHi * multFactor - valueLo = lowerBits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor - valueHi = (valueHi >> shiftFactor) + upperBits(valueLo, 32) - valueLo = lowerBits(valueLo, 32) - ``` - - The function returns `valueHi, valueLo`, representing the 32 upper bits and the 32 lower bits (respectively) of the desired result. + - Then compute `valueHi = valueHi * multFactor`. + - Then compute `valueLo = lowerBits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor`. + - Then compute `valueHi = (valueHi >> shiftFactor) + upperBits(valueLo, 32)`. + - Then compute `valueLo = lowerBits(valueLo, 32)`. + - Return `valueHi, valueLo`, representing the upper 32 and the lower 32 bits, respectively, of the result. With the functions above defined, we proceed to define the `decay` function that takes as input a uint64 value `value` and decays it by the correct decay factor relative to `epochIndexDiff` epochs. OBS: note that here, `Decay Factors(epochIndexDiff)` -denotes the value of the table relative to `epochIndexDiff` epochs, which not necessarily corresponds to the `epochIndexDiff`th -entry of the table - -`decay(value, epochIndexDiff)`: -- If `value == 0` or `epochIndexDiff==0`, return `value`. -- Else: - - Let `valueHi = upperBits(value, 32)` and `valueLo = lowerBits(value, 32)`. - - Let `m` and `n` be natural numbers such that `m + n * Decay Factors Length = epochIndexDiff`, and `m < Decay Factors Length`. - - Apply `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(Decay Factors Length), Decay Factors Exponent)` `n` times. - - Apply `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(m), Decay Factors Exponent)` once. - - The function should return `valueHi, valueLo` combined into a single `uint64`, i.e., it returns `valueHi << 32 + valueLo`. +denotes the value of the table relative to `epochIndexDiff` epochs, which not necessarily corresponds to the `epochIndexDiff`th entry of the table. + +- Let `decay(value, epochIndexDiff)` be: + - If `value == 0` or `epochIndexDiff == 0`, return `value`. + - Else: + - Let `valueHi = upperBits(value, 32)` and `valueLo = lowerBits(value, 32)`. + - Let `m` and `n` be natural numbers such that `m + n * Decay Factors Length = epochIndexDiff`, and `m < Decay Factors Length`. + - Apply `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(Decay Factors Length), Decay Factors Exponent)` `n` times. + - Apply `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(m), Decay Factors Exponent)` once. + - The function should return `valueHi, valueLo` combined into a single `uint64`, i.e., it returns `valueHi << 32 + valueLo`. Other implementations of the functions above are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of @@ -234,10 +226,9 @@ If someone did this operation in a different order, let's say 1002 * 21 / 100 * ## Potential Mana -*Potential Mana* is a raw form of Mana generated over time from the IOTA coins. Every IOTA coin (besides storage deposits) +*Potential Mana* is form of Mana generated from IOTA coins over time. Every IOTA coin (besides storage deposits) generates potential Mana. The view on the potential Mana value can be deterministically -derived from the UTXO ledger, based on the UTXO IOTA coin value and the time it was created in the UTXO metadata -(we consider the creation time as the slot index of the transaction). +derived from the UTXO ledger, based on the UTXO IOTA coin value and the time it was created, which corresponds to the `Creation Slot` of the transaction that created the UTXO. ### Rationale behind the Potential Mana formulas @@ -311,20 +302,12 @@ In the next section, we introduce the default implementation for the formulas pr ### Potential Mana Semantic Validation -- Potential Mana must and can only be consumed when the corresponding output is consumed. -- When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the -accumulated potential Mana value. There are three options: - - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be -placed in the newly created output on the output side of the transaction; - - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance -Credit (BIC) should be specified in the `Allotment` field of the transaction; - - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. -- The exact algorithm to calculate the Potential Mana generated by an output created at slot `creationSlot` i +- The algorithm to calculate the Potential Mana generated by an output created at slot `creationSlot` i (which has an epoch `creationEpoch`) and consumed at slot `consumptionSlot` (which has an epoch `consumptionEpoch`), holding `Amount` IOTA coins, is given by (again, in the pseudocode below, `slotAfterCreationEpoch` is the first slot of the epoch after the creation epoch and `firstSlotConsumptionEpoch` is the first slot of the consumption epoch) the algorithms define below. - + @@ -476,7 +459,7 @@ accounts whose BIC was changed in that slot. - When applying Mana Decay to BIC at the end of a slot, it must be applied as follows: - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`. Since all additions of allotted BIC were already decayed in that slot, only the previous value of BIC must be decayed, relative to the last slot it was decayed in, by applying: -TODO: This function is weird, it doesn't take into account the last time the BIC was decayed and the current time. +TODO: This function doesn't take into account the last time the BIC was decayed and the current time. ```go if BIC > 0: From a9e3d2be34d104ac8a90b302684a486acd72fedf Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 1 Oct 2023 14:01:42 +0100 Subject: [PATCH 120/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 74 ++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index fda0b215b..308c2e3e4 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -254,51 +254,39 @@ where δ is the difference between the creation and consumption slots. ### Potential Mana formulas with fixed point arithmetics + The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the -formula for `n > 1`, noticing that we already approximated `2^Mana Decay Factors Exponent * exp(-β * Δ * i)` by -`Mana Decay Factors(i-1)`, where `Mana Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. - -If `n > 1`: Let `c` be an integer approximation of `(exp(-β * Δ)) / (1 - exp(-β * Δ))` in the form -`c = manaDecayFactorEpochsSum * 2^(-manaDecayFactorEpochsSumExponent)`. Given the values defined in the last section, -we set `manaDecayFactorEpochsSum = TODO` and `manaDecayFactorEpochsSumExponent= TODO`. Then, -`Potential_Mana = aux + aux1 + aux2`, where: -- `aux = amount * generationPerSlot * d2 + c * amount * generationPerSlot * slotPerEpoch`; -- `aux1 = amount * generationPerSlot * d1 * Mana Decay Factors(n-1) * 2^(-Mana Decay Factors Exponent) `; -- `aux2 = -c * amount * generationPerSlot * slotPerEpoch * (Mana Decay Factors(n - 2) + 1) * 2^(-Mana Decay Factors Exponent)`; - -and -- `slotPerEpoch = 2^Slots Per Epoch Exponent` is the number of slots in an epoch. Initially, we use -`Slots Per Epoch Exponent = 13`; -- `d1 = slotAfterEpochi - creationSlot`; -- `slotAfterEpochi` is the first slot of the epoch `i + 1`; -- `d2 = consumptionSlot - firstSlotEpochJ` -- `firstSlotEpochJ` is the first slot of epoch `j` ; -- `generationPerSlot = manaGenerationRate * 2^(-manaGenerationRateExponent)` is the Mana generated by holding 1 IOTA for -1 slot. Initially, we use `manaGenerationRate = 1` and `manaGenerationRateExponent = 80 - Mana Bits Count`. This generation rate -per slot guarantees that the maximum theoretical mana in the system uses the `Mana Bits Count` available bits; -- `Mana Bits Count = 63`. - -Note that the term `aux2` has a factor `Mana Decay Factors(n - 2) + 1` instead of `Mana Decay Factors(n - 2)` since the values -in the [lookup table](#lookup-table) are rounded by below, and the term `aux2` is being subtracted by the formula. Then, by doing -this, we avoid potential gameability scenarios, since all the terms added will be rounded down in the formula. - -Rearranging the formulas above, we have that `Potential_Mana = potentialMana0 + potentialManan + potentialManan1`, -where -- `potentialMana0 = amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent) + c * amount * manaGenerationRate * -2^(Slots Per Epoch Exponent - manaGenerationRateExponent) - c * amount * manaGenerationRate * -2^(Slots Per Epoch Exponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`; -- `potentialManan = amount * d1 * Mana Decay Factors(n-1) * manaGenerationRate * 2^(-Mana Decay Factors Exponent-manaGenerationRateExponent)`; -- `potentialManan1 = -c * amount * manaGenerationRate * Mana Decay Factors(n - 2) * -2^(Slots Per Epoch Exponent - Mana Decay Factors Exponent - manaGenerationRateExponent)`. - -Analogously, we find formulas for `n < 2`: -- If `n = 1`: `Potential_Mana = amount * d1 * Mana Decay Factors(0) * manaGenerationRate * -2^(-Mana Decay Factors Exponent - manaGenerationRateExponent) + amount * d2 * manaGenerationRate * 2^(-manaGenerationRateExponent)`. -- If `n = 0`: `Potential_Mana = amount * (consumptionSlot - creationSlot) * manaGenerationRate * -2^(-manaGenerationRateExponent)`. - -In the next section, we introduce the default implementation for the formulas presented above. +formula for n>1, noticing that we already approximated 2`Decay Factors Exponent` exp(-βΔi) by +`Decay Factors(i)`, where `Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. +The parameter γ is then represented as `Generation Rate`*2-`Generation Rate Exponent`, +and exp(-βΔ)/(1 - exp(-βΔ)) is approximated by `Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. +For additional explanations about these approximations, see the Incentives Whitepaper. + +We begin by defining an auxiliary function `generateMana` that (intuitively) generates Mana without applying any type of decay +(note that we use some of the functions and constants defined in the last sections): + + * `generateMana(value,slotIndexDiff)` returns the generated mana from holding `value` tokens for `slotIndexDiff` slots, +without applying any decay: + * if `slotIndexDiff` == 0 or `Generation Rate` == 0, the function returns `0` + * otherwise, it returns `MultiplicationAndShift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. + +Now we define the function `ManaGenerationWithDecay` that actually calculates the Potential Mana using the formulas +defined in the last section (including the decays): + + * `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)` calculates the generated potential mana by holding + `amount` tokens from `slotIndexCreated` to `slotIndexTarget` and applies the decay to the result: + * If `slotIndexCreated` ≥ `slotIndexTarget`, it returns `0`. + * Otherwise, let `epochIndexCreated` and `epochIndexTarget` be the epochs to which `slotIndexCreated` and `slotIndexTarget` belongs to, respectively. We divide the remaining of the function into three cases: + * If `epochIndexCreated` == `epochIndexTarget`, it returns `generateMana(amount, slotIndexTarget-slotIndexCreated)`. + * If `epochIndexCreated` == `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, and `SlotsSinceEpochStart` be the difference between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`. Then, the function returns `manaDecayed + manaGenerated`, where + * `manaDecayed` = `decay(generateMana(amount, SlotsBeforeNextEpoch), 1)` + * `manaGenerated` = `generateMana(amount, SlotsSinceEpochStart)` + * If `epochIndexCreated` < `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, `SlotsSinceEpochStart` be the difference between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`, and `epochIndexDiff` be `epochIndexTarget - epochIndexCreated`. Then, the function returns `potentialMana_0 - potentialMana_n_1 + potentialMana_n`, where + * `potentialMana_n = decay(generateMana(amount, SlotsBeforeNextEpoch), epochIndexDiff)` + * `potentialMana_n_1 = decay(c, epochIndexDiff-1)` + * `potentialMana_0 = c + generateMana(amount, SlotsSinceEpochStart) - (c >> Generation Rate Exponent)` + * `c = MultiplicationAndShift(upperBits(amount, 32), lowerBits(amount, 32), Decay Factor Epochs Sum * Generation Rate , Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent)`. ### Potential Mana Semantic Validation From 1da2cfca3bb388133078310dc8fb3ca200241064 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 1 Oct 2023 14:06:23 +0100 Subject: [PATCH 121/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 74 --------------------------------------- 1 file changed, 74 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 308c2e3e4..72b69d0fd 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -290,80 +290,6 @@ defined in the last section (including the decays): ### Potential Mana Semantic Validation -- The algorithm to calculate the Potential Mana generated by an output created at slot `creationSlot` i -(which has an epoch `creationEpoch`) and consumed at slot `consumptionSlot` (which has an epoch `consumptionEpoch`), -holding `Amount` IOTA coins, is given by (again, in the pseudocode below, `slotAfterCreationEpoch` is the first -slot of the epoch after the creation epoch and `firstSlotConsumptionEpoch` is the first slot of the consumption -epoch) the algorithms define below. - -
Name
- - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
Valueuint64 - The amount of IOTA coins held in the output. -
creationSlotuint64 - The index of slot in which the output was created. -
consumptionSlotuint64 - The index of slot in which the output is consumed. -
- -==TODO: talk about the missing remainder== - -We begin by defining an auxiliary function that (intuitively) generates Mana without applying any type of decay -(note that we use some of the functions and constants defined in the last sections): - -```go -// generateMana calculates the generated mana from holding `value` tokens for `m` slots, without applying any decay. -func generateMana(value, m) { - if m == 0 or manaGenerationRate == 0 { - return 0 - } - return MultiplicationAndShift(value, m * manaGenerationRate, manaGenerationRateExponent) -} -``` - -Now we define the function that actually calculates the Potential Mana using the formulas defined in the last i -section (including the decays). Let `n = consumptionSlot - creationSlot`, `d1 = slotAfterCreationEpoch - creationSlot`, -and `d2 = consumptionSlot - firstSlotConsumptionEpoch`. Then, we have: - -```go -// PotentialManaWithDecay calculates the generated potential mana and applies the decay to the result. -func PotentialManaWithDecay(value, n, d1, d2) { - if n == 0: - return generateMana(value, d1 + d2 - 2^Slots Per Epoch Exponent) - else if n == 1: - return decay(generateMana(value, d1), 1) + generateMana(value, d2) - else: - aux = MultiplicationAndShift(value * manaGenerationRate, manaDecayFactorEpochsSum, manaDecayFactorEpochsSumExponent + -manaGenerationRateExponent - Slots Per Epoch Exponent) - - potentialMana_n := decay(generateMana(value, d1), n) - potentialMana_n_1 := decay(aux, n - 1) - potentialMana_0 := generateMana(value, d2) + aux - aux >> Mana Decay Factors Exponent - - return potentialMana_n - potentialMana_n_1 + potentialMana_0 - } -``` - -==TODO: talk with max about the manaGenerationRate in aux and generateMana== ## Stored Mana From 183df6650856291f67b01009146d440a4d6eef89 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 1 Oct 2023 16:54:31 +0100 Subject: [PATCH 122/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 72b69d0fd..395deead8 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -290,6 +290,43 @@ defined in the last section (including the decays): ### Potential Mana Semantic Validation +- Potential Mana must and can only be consumed when the corresponding output is consumed. +- When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the +accumulated potential Mana value. There are three options: + - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be +placed in the newly created output on the output side of the transaction; + - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance +Credit (BIC) should be specified in the `Allotment` field of the transaction; + - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. +- The exact algorithm to calculate the Potential Mana generated by an output created at slot `slotIndexCreated` and consumed at slot `slotIndexTarget` (which has an epoch `consumptionEpoch`), holding `amount` IOTA coins, is given by `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)`, where + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Amountuint64 + The amount of IOTA coins held in the output. +
slotIndexCreateduint64 + The index of slot in which the output was created. +
slotIndexTargetuint64 + The index of slot in which the output is consumed. +
## Stored Mana @@ -300,7 +337,7 @@ market development. All output types, except Foundry and Delegation Outputs, can hold stored Mana in the *Mana* field. This field represents the amount of stored Mana at the output's creation time until the time when the output is consumed without decay applied to it. -Decay must therefore be applied whenever an output containing Stored Mana is consumed. The creation slot of each output with stored Mana. +Decay must, therefore, be applied whenever an output containing Stored Mana is consumed. The creation slot of each output with stored Mana. ### Stored Mana Semantic Validation From 1d8230b8d5f8da31d2a7552d0cae0871a41e3861 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 1 Oct 2023 17:03:05 +0100 Subject: [PATCH 123/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 395deead8..c9a37c533 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -232,25 +232,25 @@ derived from the UTXO ledger, based on the UTXO IOTA coin value and the time it ### Rationale behind the Potential Mana formulas -We model the potential Mana generated by an output holding S IOTA coins as the combination of a fixed generation -per slot γS and a decay equivalent to a multiplication by exp(-βΔ) every time an epoch ends. - +We model the potential Mana generated by an output holding `S` IOTA coins as the combination of a fixed generation +per slot `γS` and a decay equivalent to a multiplication by exp(-βΔ) every time an epoch ends. + ![](./img/slots_potential_mana-2.png) -Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let n=`j`-`i`, and for -the sake of the explanation, assume n>1. All the Mana generated in epoch `i` "crosses" n decay boundaries; -thus, it must be decayed n times. The Mana generated in epoch `i`+1 "crosses" n-1 decay boundaries, so it +Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n=j-i`, and for +the sake of the explanation, assume `n`>1. All the Mana generated in epoch `i` "crosses" n decay boundaries; +thus, it must be decayed `n` times. The Mana generated in epoch `i+1` "crosses" n-1 decay boundaries, so it must be decayed n-1 times, and so on, until the Mana generated in epoch `j`, which is not decayed at all. Adding these values, we find the following formulas (where d is the number of slots in an epoch): -Potential Mana = γSd1 exp(-βΔn) + ΣγSd exp(-βΔi) + γSd2, where the summation is over i = 1,...,n-1. +Potential Mana = γSd1 exp(-βΔn) + ΣγSd exp(-βΔi) + γSd2, where the summation is over i = 1,...,n-1. Solving the sum, this results: -Potential Mana = γSd1 exp(-βΔn) + γSd2 + γSd exp(-βΔ) (1 - exp(-βΔ(n-1))) / (1-exp(-βΔ)), +Potential Mana = γSd1 exp(-βΔn) + γSd2 + γSd exp(-βΔ) (1 - exp(-βΔ(n-1))) / (1-exp(-βΔ)), -Analogously, if n=1, Potential Mana = γSd1 exp(-βΔ) + γSd2; if n=0, Potential Mana = γSδ, -where δ is the difference between the creation and consumption slots. +Analogously, if `n=1`, Potential Mana = γSd1 exp(-βΔ) + γSd2; if `n=0`, Potential Mana = γSδ, +where δ is the difference between the creation and consumption slots. ### Potential Mana formulas with fixed point arithmetics From 661c6e6424ab07078a4d6c86df058467cca4b620 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 1 Oct 2023 17:04:18 +0100 Subject: [PATCH 124/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c9a37c533..6b4cb4f8e 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -250,7 +250,7 @@ Solving the sum, this results: Potential Mana = γSd1 exp(-βΔn) + γSd2 + γSd exp(-βΔ) (1 - exp(-βΔ(n-1))) / (1-exp(-βΔ)), Analogously, if `n=1`, Potential Mana = γSd1 exp(-βΔ) + γSd2; if `n=0`, Potential Mana = γSδ, -where δ is the difference between the creation and consumption slots. +where δ is the difference between the creation and consumption slots. ### Potential Mana formulas with fixed point arithmetics From 820c18b7a0b8460bf66b52c6f3e919ce8ded3981 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 1 Oct 2023 17:05:33 +0100 Subject: [PATCH 125/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 6b4cb4f8e..ca3182c36 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -257,9 +257,9 @@ where δ is the difference between the creation and consumption slo The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the -formula for n>1, noticing that we already approximated 2`Decay Factors Exponent` exp(-βΔi) by +formula for n>1, noticing that we already approximated 2`Decay Factors Exponent` exp(-βΔi) by `Decay Factors(i)`, where `Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. -The parameter γ is then represented as `Generation Rate`*2-`Generation Rate Exponent`, +The parameter `γ` is then represented as `Generation Rate`*2-`Generation Rate Exponent`, and exp(-βΔ)/(1 - exp(-βΔ)) is approximated by `Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. For additional explanations about these approximations, see the Incentives Whitepaper. From 050e978bc046b08d072caca7280d2bb64631ba61 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 1 Oct 2023 17:06:29 +0100 Subject: [PATCH 126/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index ca3182c36..b0737475a 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -260,7 +260,7 @@ floating point arithmetics, so these formulas must be adapted for the implementa formula for n>1, noticing that we already approximated 2`Decay Factors Exponent` exp(-βΔi) by `Decay Factors(i)`, where `Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. The parameter `γ` is then represented as `Generation Rate`*2-`Generation Rate Exponent`, -and exp(-βΔ)/(1 - exp(-βΔ)) is approximated by `Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. +and exp(-βΔ)/(1 - exp(-βΔ)) is approximated by `Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. For additional explanations about these approximations, see the Incentives Whitepaper. We begin by defining an auxiliary function `generateMana` that (intuitively) generates Mana without applying any type of decay From 9658ba1b2f37bdb9fde90cdd6a2dfb177aa08b60 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 1 Oct 2023 17:08:45 +0100 Subject: [PATCH 127/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index b0737475a..9e53588c6 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -276,13 +276,13 @@ defined in the last section (including the decays): * `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)` calculates the generated potential mana by holding `amount` tokens from `slotIndexCreated` to `slotIndexTarget` and applies the decay to the result: - * If `slotIndexCreated` ≥ `slotIndexTarget`, it returns `0`. + * If `slotIndexCreated` ≥ `slotIndexTarget`, it returns `0`. * Otherwise, let `epochIndexCreated` and `epochIndexTarget` be the epochs to which `slotIndexCreated` and `slotIndexTarget` belongs to, respectively. We divide the remaining of the function into three cases: - * If `epochIndexCreated` == `epochIndexTarget`, it returns `generateMana(amount, slotIndexTarget-slotIndexCreated)`. - * If `epochIndexCreated` == `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, and `SlotsSinceEpochStart` be the difference between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`. Then, the function returns `manaDecayed + manaGenerated`, where + * If `epochIndexCreated` == `epochIndexTarget`, it returns `generateMana(amount, slotIndexTarget-slotIndexCreated)`. + * If `epochIndexCreated` == `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, and `SlotsSinceEpochStart` be the difference between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`. Then, the function returns `manaDecayed + manaGenerated`, where * `manaDecayed` = `decay(generateMana(amount, SlotsBeforeNextEpoch), 1)` * `manaGenerated` = `generateMana(amount, SlotsSinceEpochStart)` - * If `epochIndexCreated` < `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, `SlotsSinceEpochStart` be the difference between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`, and `epochIndexDiff` be `epochIndexTarget - epochIndexCreated`. Then, the function returns `potentialMana_0 - potentialMana_n_1 + potentialMana_n`, where + * If `epochIndexCreated` < `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, `SlotsSinceEpochStart` be the difference between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`, and `epochIndexDiff` be `epochIndexTarget - epochIndexCreated`. Then, the function returns `potentialMana_0 - potentialMana_n_1 + potentialMana_n`, where * `potentialMana_n = decay(generateMana(amount, SlotsBeforeNextEpoch), epochIndexDiff)` * `potentialMana_n_1 = decay(c, epochIndexDiff-1)` * `potentialMana_0 = c + generateMana(amount, SlotsSinceEpochStart) - (c >> Generation Rate Exponent)` From bd070e9eb2a11f8c250f07f063a69f49e356a24e Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 1 Oct 2023 17:12:15 +0100 Subject: [PATCH 128/157] Update tips/TIP-0039/tip-0039.md --- tips/TIP-0039/tip-0039.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 9e53588c6..ef60d0f75 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -290,14 +290,6 @@ defined in the last section (including the decays): ### Potential Mana Semantic Validation -- Potential Mana must and can only be consumed when the corresponding output is consumed. -- When the UTXO is spent, the potential Mana is lost; therefore, the user must specify what should happen to the -accumulated potential Mana value. There are three options: - - transition to stored Mana: the amount of potential Mana transitioned to the stored Mana form needs to be -placed in the newly created output on the output side of the transaction; - - transition to BIC: the amount of potential Mana that should be allotted to the account's Block Issuance -Credit (BIC) should be specified in the `Allotment` field of the transaction; - - ignored: generated Mana can be ignored so that it will be destroyed during the transaction. - The exact algorithm to calculate the Potential Mana generated by an output created at slot `slotIndexCreated` and consumed at slot `slotIndexTarget` (which has an epoch `consumptionEpoch`), holding `amount` IOTA coins, is given by `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)`, where From bb97ad945390547d4d92d4274ca18d3eac46dfe6 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Thu, 5 Oct 2023 16:08:04 +0100 Subject: [PATCH 129/157] Update tip-0039.md --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index ef60d0f75..b9ea4b875 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -285,7 +285,7 @@ defined in the last section (including the decays): * If `epochIndexCreated` < `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, `SlotsSinceEpochStart` be the difference between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`, and `epochIndexDiff` be `epochIndexTarget - epochIndexCreated`. Then, the function returns `potentialMana_0 - potentialMana_n_1 + potentialMana_n`, where * `potentialMana_n = decay(generateMana(amount, SlotsBeforeNextEpoch), epochIndexDiff)` * `potentialMana_n_1 = decay(c, epochIndexDiff-1)` - * `potentialMana_0 = c + generateMana(amount, SlotsSinceEpochStart) - (c >> Generation Rate Exponent)` + * `potentialMana_0 = c + generateMana(amount, SlotsSinceEpochStart) - (c >> Decay Factors Exponent)` * `c = MultiplicationAndShift(upperBits(amount, 32), lowerBits(amount, 32), Decay Factor Epochs Sum * Generation Rate , Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent)`. ### Potential Mana Semantic Validation From a947c82b03ff6a230dc552d06c487083d0882f4a Mon Sep 17 00:00:00 2001 From: Roman Overko Date: Mon, 16 Oct 2023 10:29:26 +0200 Subject: [PATCH 130/157] Add Roman as author --- tips/TIP-0039/tip-0039.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index b9ea4b875..223d850d1 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -2,7 +2,8 @@ tip: 39 title: Mana for IOTA 2.0 description: Define Mana, Mana dynamics, and other Mana-related concepts in the IOTA 2.0 protocol -author: TODO +author: + TODO, Roman Overko (@roman1e2f5p8s) discussions-to: TODO status: Draft type: Standards From f9353e9a6c18c31abbeea84516a1d3a7933a4a33 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 16 Oct 2023 09:38:48 +0100 Subject: [PATCH 131/157] remove a to do --- tips/TIP-0039/tip-0039.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 223d850d1..5b24371c5 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -488,8 +488,6 @@ It is highly recommended to use overflow checks for arithmetic operations when c ## Lookup Table -== TODO: If this `32` here (and above in pseudo codes) comes from `Mana Decay Factors Exponent`, -let's use the `Mana Decay Factors Exponent`?==
From 107c5d8f78945fd6bb37b9f8e0b14928fa98d87e Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 16 Oct 2023 09:42:04 +0100 Subject: [PATCH 132/157] add olivia as author --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 5b24371c5..b3db09939 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -3,7 +3,7 @@ tip: 39 title: Mana for IOTA 2.0 description: Define Mana, Mana dynamics, and other Mana-related concepts in the IOTA 2.0 protocol author: - TODO, Roman Overko (@roman1e2f5p8s) + TODO, Roman Overko (@roman1e2f5p8s) , Olivia Saa (@oliviasaa) discussions-to: TODO status: Draft type: Standards From bc7a1c47e24b8206883728bf47c05678d9cfc2f5 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Mon, 23 Oct 2023 11:55:33 +0100 Subject: [PATCH 133/157] Reorganize authors --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index b3db09939..591b076a1 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -3,7 +3,7 @@ tip: 39 title: Mana for IOTA 2.0 description: Define Mana, Mana dynamics, and other Mana-related concepts in the IOTA 2.0 protocol author: - TODO, Roman Overko (@roman1e2f5p8s) , Olivia Saa (@oliviasaa) + Olivia Saa (@oliviasaa) , Roman Overko (@roman1e2f5p8s) , Philipp Gackstatter (@PhilippGackstatter) discussions-to: TODO status: Draft type: Standards From 37edb1f52c82b37cae6adee4f04cb80c7bc12d46 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Mon, 23 Oct 2023 11:55:54 +0100 Subject: [PATCH 134/157] Format Markdown --- tips/TIP-0039/tip-0039.md | 556 ++++++++++++++++++++------------------ 1 file changed, 295 insertions(+), 261 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 591b076a1..14ddb53b6 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -2,8 +2,9 @@ tip: 39 title: Mana for IOTA 2.0 description: Define Mana, Mana dynamics, and other Mana-related concepts in the IOTA 2.0 protocol -author: - Olivia Saa (@oliviasaa) , Roman Overko (@roman1e2f5p8s) , Philipp Gackstatter (@PhilippGackstatter) +author: + Olivia Saa (@oliviasaa) , Roman Overko (@roman1e2f5p8s) , Philipp + Gackstatter (@PhilippGackstatter) discussions-to: TODO status: Draft type: Standards @@ -17,39 +18,44 @@ requires: TIP-42 1. [Summary](#summary) 2. [Motivation](#motivation) 3. [Building Blocks](#building-blocks) - - [Data Types \& Subschema Notation](#data-types--subschema-notation) - - [Protocol Parameters](#protocol-parameters) + - [Data Types \& Subschema Notation](#data-types--subschema-notation) + - [Protocol Parameters](#protocol-parameters) 4. [Mana design](#mana-design) - - [Mana Burn](#mana-burn) - - [Reference Mana Cost](#reference-mana-cost) - - [Mana Decay](#mana-decay) - - [Mana Decay Parameters](#mana-decay-parameters) - - [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) - - [How to use the lookup table](#how-to-use-the-lookup-table) - - [Potential Mana](#potential-mana) - - [Potential Mana Semantic Validation](#potential-mana-semantic-validation) - - [Stored Mana](#stored-mana) - - [Stored Mana Semantic Validation](#stored-mana-semantic-validation) - - [Block Issuance Credit](#block-issuance-credit) - - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) - - [Mana rewards](#mana-rewards) - - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) - - [Mana Transaction Validation Rules](#mana-transaction-validation-rules) - - [Lookup Table](#lookup-table) + - [Mana Burn](#mana-burn) + - [Reference Mana Cost](#reference-mana-cost) + - [Mana Decay](#mana-decay) + - [Mana Decay Parameters](#mana-decay-parameters) + - [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) + - [How to use the lookup table](#how-to-use-the-lookup-table) + - [Potential Mana](#potential-mana) + - [Potential Mana Semantic Validation](#potential-mana-semantic-validation) + - [Stored Mana](#stored-mana) + - [Stored Mana Semantic Validation](#stored-mana-semantic-validation) + - [Block Issuance Credit](#block-issuance-credit) + - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) + - [Mana rewards](#mana-rewards) + - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) + - [Mana Transaction Validation Rules](#mana-transaction-validation-rules) + - [Lookup Table](#lookup-table) 5. [Copyright](#copyright) # Summary -This document defines the Mana-related concepts and the Mana dynamics in the IOTA 2.0 protocol. -The TIP defines the two types of Mana, namely **Potential Mana** and **Stored Mana,** as well as the -**Block Issuance Credit (BIC)** that Mana can be allotted to. +This document defines the Mana-related concepts and the Mana dynamics in the IOTA 2.0 protocol. The TIP defines the two +types of Mana, namely **Potential Mana** and **Stored Mana,** as well as the **Block Issuance Credit (BIC)** that Mana +can be allotted to. # Motivation -Mana is a resource used to determine the allowed throughput of a user and as a payment form for block issuance. Mana can be obtained by constructive and profitable actions for the network, like token holding or engagement in securing the network. Additionally, owning Mana is necessary to use the network by issuing -blocks, so it plays a core role in the IOTA Tokenomics. The following document gives a high-level overview of -Mana types and its dynamics. Mana is a crucial change introduced in the IOTA 2.0 protocol, next to staking, -delegation and congestion control changes. This document works with the Congestion Control Algorithm with Mana, in which block issuers must allot Mana to their account to increase their Block Issuance Credit balance. In order to issue a block a certain amount of BIC is deducted from the issuer account balance and burned. In order to issue blocks and use all functionalitiy related to Mana, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). +Mana is a resource used to determine the allowed throughput of a user and as a payment form for block issuance. Mana can +be obtained by constructive and profitable actions for the network, like token holding or engagement in securing the +network. Additionally, owning Mana is necessary to use the network by issuing blocks, so it plays a core role in the +IOTA Tokenomics. The following document gives a high-level overview of Mana types and its dynamics. Mana is a crucial +change introduced in the IOTA 2.0 protocol, next to staking, delegation and congestion control changes. This document +works with the Congestion Control Algorithm with Mana, in which block issuers must allot Mana to their account to +increase their Block Issuance Credit balance. In order to issue a block a certain amount of BIC is deducted from the +issuer account balance and burned. In order to issue blocks and use all functionalitiy related to Mana, the user is +required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). # Building Blocks @@ -64,78 +70,90 @@ Protocol parameters used throughout this TIP are defined in [TIP-49](../TIP-0049 # Mana Design Mana is a core element of the IOTA incentive scheme. It is a resource that can be obtained through: + - generation by holding IOTA coins; - as a reward for staking IOTA coins; - as a reward for delegating IOTA coins; - or simply received or bought from other IOTA users. It is an essential element of the IOTA protocol, as it is used: + - to determine the allowed throughput of an account in the congestion control; - as a payment for block issuance; - as a core part of the IOTA Tokenomics and incentivization scheme. **Mana** can have different forms, each of which is described in the following sections. -- [**Stored Mana**](#stored-mana) is Mana that is stored in UTXOs and can consequently be moved on the UTXO ledger, which allows for Mana Market development. -- [**Potential Mana**](#potential-mana) is generated by holding IOTA coins. The longer the IOTA coins were unspent, the more Potential Mana is generated. When an output is spent, its Potential Mana is released and can be transitioned to one of its more explicit forms, i.e. Stored Mana or Block Issuance Credits. -- [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana that can be used to issue blocks. During a transaction, Stored or Potential Mana can be _allotted_ which moves the Mana off the UTXO ledger and converts it to BIC. Only this form of Mana be used to issue blocks. -- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA tokens. The Mana rewarded from these activities is not registered in the UTXO ledger and must be moved to it when claiming rewards as described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). + +- [**Stored Mana**](#stored-mana) is Mana that is stored in UTXOs and can consequently be moved on the UTXO ledger, + which allows for Mana Market development. +- [**Potential Mana**](#potential-mana) is generated by holding IOTA coins. The longer the IOTA coins were unspent, the + more Potential Mana is generated. When an output is spent, its Potential Mana is released and can be transitioned to + one of its more explicit forms, i.e. Stored Mana or Block Issuance Credits. +- [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana that can be used to issue blocks. During + a transaction, Stored or Potential Mana can be _allotted_ which moves the Mana off the UTXO ledger and converts it to + BIC. Only this form of Mana be used to issue blocks. +- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA tokens. The Mana + rewarded from these activities is not registered in the UTXO ledger and must be moved to it when claiming rewards as + described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). ## Mana Burn -The **Mana holdings** of a user are the sum of all the Potential Mana and Stored Mana (but not the Mana Rewards) in their Account Output -that they use to issue blocks. According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a -certain amount of Mana dictated by the work score of the block and the Reference Mana Cost (RMC). The Mana burned by the -block is subtracted from the block issuer's BIC balance. Users who overspend Mana (i.e., try to issue more blocks -than their Mana Holdings allow) will have their account locked until their debt is paid. +The **Mana holdings** of a user are the sum of all the Potential Mana and Stored Mana (but not the Mana Rewards) in +their Account Output that they use to issue blocks. According to the congestion control mechanism, during each block +issuance, the block issuer needs to burn a certain amount of Mana dictated by the work score of the block and the +Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Users who +overspend Mana (i.e., try to issue more blocks than their Mana Holdings allow) will have their account locked until +their debt is paid. ### Reference Mana Cost -*Reference Mana Cost (RMC)* is used to decide how much Mana should be burned from BIC by each block in that slot. -RMC is computed according to an algorithm based on recent traffic activity: the algorithm counts the number of -blocks in slots that are *Maximum Committable Age (MCA)* slots in the past so that all nodes agree on that value of -RMC and know this value in advance (before issuing the block). +_Reference Mana Cost (RMC)_ is used to decide how much Mana should be burned from BIC by each block in that slot. RMC is +computed according to an algorithm based on recent traffic activity: the algorithm counts the number of blocks in slots +that are _Maximum Committable Age (MCA)_ slots in the past so that all nodes agree on that value of RMC and know this +value in advance (before issuing the block). From a high-level perspective, the RMC algorithm works as follows: + - If the number of blocks in slot `i - MCA` is larger than a given threshold, then the RMC increases. - Otherwise, if the activity is low, the RMC decreases. -- The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly -becomes too large for the majority of users, and activity drops. +- The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes + too large for the majority of users, and activity drops. -The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid -price manipulations by malicious actors. Note that blocks from issuers with negative BIC balances are excluded with -respect to the RMC calculation, but they do make part of the slot commitment. To limit fluctuations in the RMC, -it is recommended to update its value every MCA slot at least. +The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid price +manipulations by malicious actors. Note that blocks from issuers with negative BIC balances are excluded with respect to +the RMC calculation, but they do make part of the slot commitment. To limit fluctuations in the RMC, it is recommended +to update its value every MCA slot at least. ## Mana Decay -Mana Decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana -generation both from IOTA coins and the staking mechanism, which will be discussed in detail in the next sections. -To guarantee non-gameability (e.g., splitting accounts or other behaviors that are not helpful for the system -well-functioning) and the fairness of Mana, the same global decay factor needs -to be applied to all the above-mentioned forms of Mana. - -As the exact formulas in which the decay factor will be applied might differ among the Mana types, it is essential to point -out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives Whitepaper (TODO: Link) -provides the specific formula for the decay function in Appendix A. - -Applying decay for the generation of new Mana and staking rewards is conceptually straightforward since it is done at the time of -storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO spending. In -any of those cases, the node must calculate the decay based on epoch indices, not local times. Every -2Slots Per Epoch Exponent slots, the epoch changes, meaning that every set of consecutive 2Slots Per Epoch Exponent -slots will be in the same epoch. - -The decay parameter `β` (together with the Mana generation parameter `Mana Structure::Generation Rate`) was set so the maximum theoretical Mana in -the system is smaller than 2Bits Count - 1, where `Bits Count` refers to the `Mana Structure::Bits Count` protocol parameter. This means that, even though Mana is stored as a uint64, it effectively uses -less than 64 bits (in the case of BIC, it uses at most `Bits Count + 1` bits, `Bits Count` for the value and one -for the sign). Note that the system will almost certainly never use all the `Bits Count` to store Mana since, for the Mana -supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work with Mana values -way smaller than 2Bits Count - 1; however, we must count on what would be an unreasonably large value in practice -to avoid overflowing of the variables even if with a minimal probability. +Mana Decay is introduced as a control mechanism of the Mana dynamics, altogether with the rate for the Mana generation +both from IOTA coins and the staking mechanism, which will be discussed in detail in the next sections. To guarantee +non-gameability (e.g., splitting accounts or other behaviors that are not helpful for the system well-functioning) and +the fairness of Mana, the same global decay factor needs to be applied to all the above-mentioned forms of Mana. + +As the exact formulas in which the decay factor will be applied might differ among the Mana types, it is essential to +point out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives +Whitepaper (TODO: Link) provides the specific formula for the decay function in Appendix A. + +Applying decay for the generation of new Mana and staking rewards is conceptually straightforward since it is done at +the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO +spending. In any of those cases, the node must calculate the decay based on epoch indices, not local times. Every +2Slots Per Epoch Exponent slots, the epoch changes, meaning that every set of consecutive +2Slots Per Epoch Exponent slots will be in the same epoch. + +The decay parameter `β` (together with the Mana generation parameter `Mana Structure::Generation Rate`) was set so the +maximum theoretical Mana in the system is smaller than 2Bits Count - 1, where `Bits Count` +refers to the `Mana Structure::Bits Count` protocol parameter. This means that, even though Mana is stored as a uint64, +it effectively uses less than 64 bits (in the case of BIC, it uses at most `Bits Count + 1` bits, `Bits Count` for the +value and one for the sign). Note that the system will almost certainly never use all the `Bits Count` to store Mana +since, for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work +with Mana values way smaller than 2Bits Count - 1; however, we must count on what would be an +unreasonably large value in practice to avoid overflowing of the variables even if with a minimal probability. ### Mana Decay Parameters -The tables below describe the key parameters used for the Mana decay calculations in the next sections of this TIP. Notice that -the parameters in the first table are only used in the explanations in this TIP, but not in the code. +The tables below describe the key parameters used for the Mana decay calculations in the next sections of this TIP. +Notice that the parameters in the first table are only used in the explanations in this TIP, but not in the code.
Lookup Table: Decays for Mana in decay index granularity scaled to 232
@@ -162,33 +180,33 @@ the parameters in the first table are only used in the explanations in this TIP,
-Additionally, we use the protocol parameters, as defined in [TIP-49], and `Decay Factors Length`, -defined as the length of the lookup Table `Decay Factors`. +Additionally, we use the protocol parameters, as defined in [TIP-49], and `Decay Factors Length`, defined as the length +of the lookup Table `Decay Factors`. ## Mana and fixed point arithmetics -Floating point operations might lead to inconsistencies among results in different nodes due to the different -rounding behaviors in different architectures. The results of the operations involving floating point variables might -differ by amounts that are considered negligible for the modules that deal with local decisions (as the congestion -control module, for example); however, differences that would be considered negligible by those modules can be -fatal for the transaction validation and slot commitments, leading to forks and other undesirable behaviors in the -system. For that reason, fixed point arithmetics (which do not expose the nodes to these rounding divergencies) -must be used in all the modules that require exact consensus over values. In particular, all the Mana and rewards -calculations have to be done with fixed point arithmetics. - -In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly -other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. -Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of -2Decay Factors Exponentexp(-βΔn), for different values of `n` ranging from 1 to `Decay Factors Length`. -For the lookup table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, -`Slot Duration in Seconds` = 10, (which implies that `Δ = 0.002597666159`), and `β = 1/3` per year. +Floating point operations might lead to inconsistencies among results in different nodes due to the different rounding +behaviors in different architectures. The results of the operations involving floating point variables might differ by +amounts that are considered negligible for the modules that deal with local decisions (as the congestion control module, +for example); however, differences that would be considered negligible by those modules can be fatal for the transaction +validation and slot commitments, leading to forks and other undesirable behaviors in the system. For that reason, fixed +point arithmetics (which do not expose the nodes to these rounding divergencies) must be used in all the modules that +require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed +point arithmetics. + +In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly +other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. +Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of 2Decay Factors +Exponentexp(-βΔn), for different values of `n` ranging from 1 to `Decay Factors Length`. For the lookup +table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, +`Slot Duration in Seconds` = 10, (which implies that `Δ = 0.002597666159`), and `β = 1/3` per year. ### How to use the lookup table -In this section, we define a function `decay(value, epochIndexDiff)`, that decays an amount of Mana `value` by the -factor relative to `epochIndexDiff` epochs. Note that the table `Decay Factors` defined above only gives the values -of decays factors for up to `Decay Factors Length` epochs. To calculate the decay for larger periods of time, we combine -values defined in the [lookup table](#lookup-table) for other numbers smaller than `Decay Factors Length`, using an +In this section, we define a function `decay(value, epochIndexDiff)`, that decays an amount of Mana `value` by the +factor relative to `epochIndexDiff` epochs. Note that the table `Decay Factors` defined above only gives the values of +decays factors for up to `Decay Factors Length` epochs. To calculate the decay for larger periods of time, we combine +values defined in the [lookup table](#lookup-table) for other numbers smaller than `Decay Factors Length`, using an algorithm that will be defined below. First, we define three auxiliary functions: - Let `upperBits(value, n)` be: given a uint64 integer `value`, returns its upper `n` bits @@ -196,102 +214,125 @@ algorithm that will be defined below. First, we define three auxiliary functions - `MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the result - of a multiplication of a uint64 by a uint32, shifted `shiftFactor` times to the right, whenever this result is smaller - than 264. To do so, it uses the following algorithm: - - Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than 264, `multFactor` be an integer smaller than 232, and `shiftFactor` be an integer between 0 and 32. - - Let `>>` be a right shift (thus, `>>n` means shifting to the right `n` times). Analogously, let `<<` be a left shift. - - Then compute `valueHi = valueHi * multFactor`. - - Then compute `valueLo = lowerBits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor`. + - Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than 264, + `multFactor` be an integer smaller than 232, and `shiftFactor` be an integer between 0 + and 32. + - Let `>>` be a right shift (thus, `>>n` means shifting to the right `n` times). Analogously, let `<<` be a left + shift. + - Then compute `valueHi = valueHi * multFactor`. + - Then compute + `valueLo = lowerBits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor`. - Then compute `valueHi = (valueHi >> shiftFactor) + upperBits(valueLo, 32)`. - Then compute `valueLo = lowerBits(valueLo, 32)`. - Return `valueHi, valueLo`, representing the upper 32 and the lower 32 bits, respectively, of the result. -With the functions above defined, we proceed to define the `decay` function that takes as input a uint64 value `value` -and decays it by the correct decay factor relative to `epochIndexDiff` epochs. OBS: note that here, `Decay Factors(epochIndexDiff)` -denotes the value of the table relative to `epochIndexDiff` epochs, which not necessarily corresponds to the `epochIndexDiff`th entry of the table. +With the functions above defined, we proceed to define the `decay` function that takes as input a uint64 value `value` +and decays it by the correct decay factor relative to `epochIndexDiff` epochs. OBS: note that here, +`Decay Factors(epochIndexDiff)` denotes the value of the table relative to `epochIndexDiff` epochs, which not +necessarily corresponds to the `epochIndexDiff`th entry of the table. -- Let `decay(value, epochIndexDiff)` be: - - If `value == 0` or `epochIndexDiff == 0`, return `value`. +- Let `decay(value, epochIndexDiff)` be: + - If `value == 0` or `epochIndexDiff == 0`, return `value`. - Else: - Let `valueHi = upperBits(value, 32)` and `valueLo = lowerBits(value, 32)`. - - Let `m` and `n` be natural numbers such that `m + n * Decay Factors Length = epochIndexDiff`, and `m < Decay Factors Length`. - - Apply `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(Decay Factors Length), Decay Factors Exponent)` `n` times. - - Apply `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(m), Decay Factors Exponent)` once. - - The function should return `valueHi, valueLo` combined into a single `uint64`, i.e., it returns `valueHi << 32 + valueLo`. - -Other implementations of the functions above are possible; however, one must be careful with the order of -operations, which must be done as defined above. Having a well-defined order is crucial since sequences of -divisions and multiplications with integers might lead to different results when the order is altered. -Example: suppose one needs to calculate 1002 * 99 / 100 *21 / 100. Following the left-to-right order, this -would result in 1002 * 99 / 100 * 21 / 100 = 99198 / 100 * 21 / 100 = 991 * 21 / 100 = 20811 / 100 = 208. -If someone did this operation in a different order, let's say 1002 * 21 / 100 * 99 / 100, the result would be -1002 * 21 / 100 * 99 / 100 = 21042 / 100 * 99 / 100 = 210 * 99 / 100 = 20790 / 100 = 207. + - Let `m` and `n` be natural numbers such that `m + n * Decay Factors Length = epochIndexDiff`, and + `m < Decay Factors Length`. + - Apply + `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(Decay Factors Length), Decay Factors Exponent)` + `n` times. + - Apply `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(m), Decay Factors Exponent)` + once. + - The function should return `valueHi, valueLo` combined into a single `uint64`, i.e., it returns + `valueHi << 32 + valueLo`. + +Other implementations of the functions above are possible; however, one must be careful with the order of operations, +which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and +multiplications with integers might lead to different results when the order is altered. Example: suppose one needs to +calculate 1002 * 99 / 100 *21 / 100. Following the left-to-right order, this would result in 1002 _ 99 / 100 _ 21 / 100 += 99198 / 100 _ 21 / 100 = 991 _ 21 / 100 = 20811 / 100 = 208. If someone did this operation in a different order, let's +say 1002 _ 21 / 100 _ 99 / 100, the result would be 1002 _ 21 / 100 _ 99 / 100 = 21042 / 100 _ 99 / 100 = 210 _ 99 / 100 += 20790 / 100 = 207. ## Potential Mana -*Potential Mana* is form of Mana generated from IOTA coins over time. Every IOTA coin (besides storage deposits) -generates potential Mana. The view on the potential Mana value can be deterministically -derived from the UTXO ledger, based on the UTXO IOTA coin value and the time it was created, which corresponds to the `Creation Slot` of the transaction that created the UTXO. +_Potential Mana_ is form of Mana generated from IOTA coins over time. Every IOTA coin (besides storage deposits) +generates potential Mana. The view on the potential Mana value can be deterministically derived from the UTXO ledger, +based on the UTXO IOTA coin value and the time it was created, which corresponds to the `Creation Slot` of the +transaction that created the UTXO. ### Rationale behind the Potential Mana formulas -We model the potential Mana generated by an output holding `S` IOTA coins as the combination of a fixed generation -per slot `γS` and a decay equivalent to a multiplication by exp(-βΔ) every time an epoch ends. +We model the potential Mana generated by an output holding `S` IOTA coins as the combination of a fixed generation per +slot `γS` and a decay equivalent to a multiplication by exp(-βΔ) every time an epoch ends. ![](./img/slots_potential_mana-2.png) -Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n=j-i`, and for -the sake of the explanation, assume `n`>1. All the Mana generated in epoch `i` "crosses" n decay boundaries; -thus, it must be decayed `n` times. The Mana generated in epoch `i+1` "crosses" n-1 decay boundaries, so it -must be decayed n-1 times, and so on, until the Mana generated in epoch `j`, which is not decayed at all. -Adding these values, we find the following formulas (where d is the number of slots in an epoch): +Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n=j-i`, and for the sake of +the explanation, assume `n`>1. All the Mana generated in epoch `i` "crosses" n decay boundaries; thus, it must be +decayed `n` times. The Mana generated in epoch `i+1` "crosses" n-1 decay boundaries, so it must be decayed n-1 times, +and so on, until the Mana generated in epoch `j`, which is not decayed at all. Adding these values, we find the +following formulas (where d is the number of slots in an epoch): -Potential Mana = γSd1 exp(-βΔn) + ΣγSd exp(-βΔi) + γSd2, where the summation is over i = 1,...,n-1. +Potential Mana = γSd1 exp(-βΔn) + ΣγSd exp(-βΔi) + γSd2, where the summation is over +i = 1,...,n-1. Solving the sum, this results: -Potential Mana = γSd1 exp(-βΔn) + γSd2 + γSd exp(-βΔ) (1 - exp(-βΔ(n-1))) / (1-exp(-βΔ)), +Potential Mana = γSd1 exp(-βΔn) + γSd2 + γSd exp(-βΔ) (1 - exp(-βΔ(n-1))) / +(1-exp(-βΔ)), -Analogously, if `n=1`, Potential Mana = γSd1 exp(-βΔ) + γSd2; if `n=0`, Potential Mana = γSδ, -where δ is the difference between the creation and consumption slots. +Analogously, if `n=1`, Potential Mana = γSd1 exp(-βΔ) + γSd2; if `n=0`, +Potential Mana = γSδ, where δ is the difference between the creation and consumption slots. ### Potential Mana formulas with fixed point arithmetics +The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating +point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for +n>1, noticing that we already approximated 2`Decay Factors Exponent` exp(-βΔi) by +`Decay Factors(i)`, where `Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. The +parameter `γ` is then represented as `Generation Rate`*2-`Generation Rate Exponent`, and +exp(-βΔ)/(1 - exp(-βΔ)) is approximated by +`Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. For additional explanations +about these approximations, see the Incentives Whitepaper. -The formulas found in the last section are the exact formulas for the model proposed. However, we must not use -floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the -formula for n>1, noticing that we already approximated 2`Decay Factors Exponent` exp(-βΔi) by -`Decay Factors(i)`, where `Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. -The parameter `γ` is then represented as `Generation Rate`*2-`Generation Rate Exponent`, -and exp(-βΔ)/(1 - exp(-βΔ)) is approximated by `Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. -For additional explanations about these approximations, see the Incentives Whitepaper. +We begin by defining an auxiliary function `generateMana` that (intuitively) generates Mana without applying any type of +decay (note that we use some of the functions and constants defined in the last sections): -We begin by defining an auxiliary function `generateMana` that (intuitively) generates Mana without applying any type of decay -(note that we use some of the functions and constants defined in the last sections): +- `generateMana(value,slotIndexDiff)` returns the generated mana from holding `value` tokens for `slotIndexDiff` slots, + without applying any decay: _ if `slotIndexDiff` == 0 or `Generation Rate` == 0, the function returns `0` _ otherwise, + it returns `MultiplicationAndShift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. - * `generateMana(value,slotIndexDiff)` returns the generated mana from holding `value` tokens for `slotIndexDiff` slots, -without applying any decay: - * if `slotIndexDiff` == 0 or `Generation Rate` == 0, the function returns `0` - * otherwise, it returns `MultiplicationAndShift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. - -Now we define the function `ManaGenerationWithDecay` that actually calculates the Potential Mana using the formulas +Now we define the function `ManaGenerationWithDecay` that actually calculates the Potential Mana using the formulas defined in the last section (including the decays): - * `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)` calculates the generated potential mana by holding - `amount` tokens from `slotIndexCreated` to `slotIndexTarget` and applies the decay to the result: - * If `slotIndexCreated` ≥ `slotIndexTarget`, it returns `0`. - * Otherwise, let `epochIndexCreated` and `epochIndexTarget` be the epochs to which `slotIndexCreated` and `slotIndexTarget` belongs to, respectively. We divide the remaining of the function into three cases: - * If `epochIndexCreated` == `epochIndexTarget`, it returns `generateMana(amount, slotIndexTarget-slotIndexCreated)`. - * If `epochIndexCreated` == `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, and `SlotsSinceEpochStart` be the difference between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`. Then, the function returns `manaDecayed + manaGenerated`, where - * `manaDecayed` = `decay(generateMana(amount, SlotsBeforeNextEpoch), 1)` - * `manaGenerated` = `generateMana(amount, SlotsSinceEpochStart)` - * If `epochIndexCreated` < `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, `SlotsSinceEpochStart` be the difference between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`, and `epochIndexDiff` be `epochIndexTarget - epochIndexCreated`. Then, the function returns `potentialMana_0 - potentialMana_n_1 + potentialMana_n`, where - * `potentialMana_n = decay(generateMana(amount, SlotsBeforeNextEpoch), epochIndexDiff)` - * `potentialMana_n_1 = decay(c, epochIndexDiff-1)` - * `potentialMana_0 = c + generateMana(amount, SlotsSinceEpochStart) - (c >> Decay Factors Exponent)` - * `c = MultiplicationAndShift(upperBits(amount, 32), lowerBits(amount, 32), Decay Factor Epochs Sum * Generation Rate , Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent)`. +- `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)` calculates the generated potential mana by + holding `amount` tokens from `slotIndexCreated` to `slotIndexTarget` and applies the decay to the result: + - If `slotIndexCreated` ≥ `slotIndexTarget`, it returns `0`. + - Otherwise, let `epochIndexCreated` and `epochIndexTarget` be the epochs to which `slotIndexCreated` and + `slotIndexTarget` belongs to, respectively. We divide the remaining of the function into three cases: + - If `epochIndexCreated` == `epochIndexTarget`, it returns + `generateMana(amount, slotIndexTarget-slotIndexCreated)`. + - If `epochIndexCreated` == `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between + `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, and `SlotsSinceEpochStart` be the difference + between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`. Then, the function returns + `manaDecayed + manaGenerated`, where + - `manaDecayed` = `decay(generateMana(amount, SlotsBeforeNextEpoch), 1)` + - `manaGenerated` = `generateMana(amount, SlotsSinceEpochStart)` + - If `epochIndexCreated` < `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between + `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, `SlotsSinceEpochStart` be the difference + between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`, and `epochIndexDiff` be + `epochIndexTarget - epochIndexCreated`. Then, the function returns + `potentialMana_0 - potentialMana_n_1 + potentialMana_n`, where + - `potentialMana_n = decay(generateMana(amount, SlotsBeforeNextEpoch), epochIndexDiff)` + - `potentialMana_n_1 = decay(c, epochIndexDiff-1)` + - `potentialMana_0 = c + generateMana(amount, SlotsSinceEpochStart) - (c >> Decay Factors Exponent)` + - `c = MultiplicationAndShift(upperBits(amount, 32), lowerBits(amount, 32), Decay Factor Epochs Sum * Generation Rate , Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent)`. ### Potential Mana Semantic Validation -- The exact algorithm to calculate the Potential Mana generated by an output created at slot `slotIndexCreated` and consumed at slot `slotIndexTarget` (which has an epoch `consumptionEpoch`), holding `amount` IOTA coins, is given by `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)`, where +- The exact algorithm to calculate the Potential Mana generated by an output created at slot `slotIndexCreated` and +consumed at slot `slotIndexTarget` (which has an epoch `consumptionEpoch`), holding `amount` IOTA coins, is given by +`ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)`, where @@ -323,171 +364,164 @@ defined in the last section (including the decays): ## Stored Mana -*Stored Mana* is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA -tokens) of Mana that can be transferred within certain rules between different users, which allows for Mana -market development. +_Stored Mana_ is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA +tokens) of Mana that can be transferred within certain rules between different users, which allows for Mana market +development. -All output types, except Foundry and Delegation Outputs, can hold stored Mana in the *Mana* field. This field represents the -amount of stored Mana at the output's creation time until the time when the output is consumed without decay applied to it. +All output types, except Foundry and Delegation Outputs, can hold stored Mana in the _Mana_ field. This field represents +the amount of stored Mana at the output's creation time until the time when the output is consumed without decay applied +to it. -Decay must, therefore, be applied whenever an output containing Stored Mana is consumed. The creation slot of each output with stored Mana. +Decay must, therefore, be applied whenever an output containing Stored Mana is consumed. The creation slot of each +output with stored Mana. ### Stored Mana Semantic Validation -- Stored Mana must be decayed before it is transferred into a new output as follows: - - Let `manaAmount`, `consumptionSlot`, and `creationSlot`, be -
Name
- - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
manaAmountuint64 - The amount of stored Mana held by the output. -
creationSlotuint64 - The index of slot in which the output was created. -
consumptionSlotuint64 - The index of slot in which the output is consumed. -
- +- Stored Mana must be decayed before it is transferred into a new output as follows: + - Let `manaAmount`, `consumptionSlot`, and `creationSlot`, be + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
manaAmountuint64 + The amount of stored Mana held by the output. +
creationSlotuint64 + The index of slot in which the output was created. +
consumptionSlotuint64 + The index of slot in which the output is consumed. +
+ The algorithm to decay the stored Mana is as follows: -```go +```go creationEpoch = epoch(creationSlot) consumptionEpoch = epoch(consumptionSlot) if creationEpoch == consumptionEpoch: newManaAmount = manaAmount -else: +else: newManaAmount = decay(manaAmount, consumptionEpoch - creationEpoch) ``` - + ## Block Issuance Credit -*Block Issuance Credit (BIC)* Mana is used for congestion control, i.e., to pay for blocks to be scheduled and -gossiped around the network and seen by everyone. Congestion control manages which blocks should be gossiped to -neighbors based on Mana burned from the block issuance credits by the block. It is important to distinguish -between **blocks** and **transactions**: congestion control only deals with blocks, which are the containers that carry transactions around the network. It does not care about the transactions inside the blocks. +_Block Issuance Credit (BIC)_ Mana is used for congestion control, i.e., to pay for blocks to be scheduled and gossiped +around the network and seen by everyone. Congestion control manages which blocks should be gossiped to neighbors based +on Mana burned from the block issuance credits by the block. It is important to distinguish between **blocks** and +**transactions**: congestion control only deals with blocks, which are the containers that carry transactions around the +network. It does not care about the transactions inside the blocks. -The example below shows a ledger with a conflicting branch (perhaps due to a double spend), so only one branch -(either the set of red or the set of green transactions) can ultimately modify the ledger, not both. -However, all these blocks must be gossiped, whether they contain red or green transactions. Thus, they must pay for -the BIC used to get through schedulers regardless of whether the transaction within modifies the ledger. This is -why BIC cannot be burned by a transaction - it can only be burned by a block. +The example below shows a ledger with a conflicting branch (perhaps due to a double spend), so only one branch (either +the set of red or the set of green transactions) can ultimately modify the ledger, not both. However, all these blocks +must be gossiped, whether they contain red or green transactions. Thus, they must pay for the BIC used to get through +schedulers regardless of whether the transaction within modifies the ledger. This is why BIC cannot be burned by a +transaction - it can only be burned by a block. ![](./img/data_flow_overview.png) -Because a block cannot modify the UTXO ledger but the Mana the block burns must be deducted from the account's BIC balance, the BIC is stored in an accounts ledger. This ledger is a map from an Account ID to block issuer data, which includes the BIC balance, the block issuer keys and when the Block Issuer Feature expires among other data. This separate ledger is partly derived from the Block Issuer Feature in an account in the UTXO ledger. The BIC balance of an account can only be modified in two ways: -- BIC is subtracted from the ledger when the corresponding account issues a block signed by one of its Block Issuer Keys. +Because a block cannot modify the UTXO ledger but the Mana the block burns must be deducted from the account's BIC +balance, the BIC is stored in an accounts ledger. This ledger is a map from an Account ID to block issuer data, which +includes the BIC balance, the block issuer keys and when the Block Issuer Feature expires among other data. This +separate ledger is partly derived from the Block Issuer Feature in an account in the UTXO ledger. The BIC balance of an +account can only be modified in two ways: + +- BIC is subtracted from the ledger when the corresponding account issues a block signed by one of its Block Issuer + Keys. - BIC is increased in the ledger when a transaction allots Mana to that account. -Updates to the BIC balance happen upon slot commitments. Mana Decay is applied to the BIC for the -accounts whose BIC was changed in that slot. +Updates to the BIC balance happen upon slot commitments. Mana Decay is applied to the BIC for the accounts whose BIC was +changed in that slot. ### Block Issuance Credit Semantic Validation - When applying Mana Decay to BIC at the end of a slot, it must be applied as follows: - - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`. Since all additions of allotted BIC were already decayed in that slot, only the previous value of BIC must be decayed, relative to the last slot it was decayed in, by applying: + - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`. Since all additions of allotted BIC + were already decayed in that slot, only the previous value of BIC must be decayed, relative to the last slot it was + decayed in, by applying: TODO: This function doesn't take into account the last time the BIC was decayed and the current time. -```go +```go if BIC > 0: new_BIC = decay(BIC, 1) -else: - new_BIC = BIC +else: + new_BIC = BIC ``` ## Mana rewards -*Mana rewards* are used to reward for participation in staking for validation and delegating IOTA coins. Rewarding +_Mana rewards_ are used to reward for participation in staking for validation and delegating IOTA coins. Rewarding validators and delegators with Mana is reasonable as it does not extract value from other IOTA coin holders. ### Mana Rewards Semantic Validation - Mana rewards must be calculated on a per-epoch basis. - Mana rewards must become available for claiming when the last slot of the epoch is committed to. -- Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or -delegated. +- Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or + delegated. - Mana rewards must be put on outputs as stored Mana on the output side of the transaction. -- The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: - - Let `reward`, `rewardEpoch`, and `claimingSlotEpoch` be as follows: - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
rewarduint64 - The amount of Mana rewards available to be claimed for staking or delegation for a specific epoch. -
rewardEpochuint64 - The index of the epoch for which Mana rewards are claimed. -
claimingSlotEpochuint64 - The epoch of the slot in which the Mana rewards are claimed. -
- - - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the [lookup table](#lookup-table) and the algorithm -defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the -rewards by applying `reward = decay(reward, n)`. - - If `n = 0`, the amount to be put on outputs is the entire `reward`. +- The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: - Let + `reward`, `rewardEpoch`, and `claimingSlotEpoch` be as follows: + + +
Name TypeDescription
reward uint64 The amount of Mana rewards available to be + claimed for staking or delegation for a specific epoch.
rewardEpoch uint64 The + index of the epoch for which Mana rewards are claimed.
claimingSlotEpoch uint64 The epoch of the slot in which the Mana rewards are claimed.
+ - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the [lookup table](#lookup-table) and the algorithm + defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the + rewards by applying `reward = decay(reward, n)`. - If `n = 0`, the amount to be put on outputs is the entire `reward`. ## Mana Transaction Validation Rules -- Let `Total Mana In` be the total amount of Mana on the input side of a transaction, consisting of `Total Potential Mana + Total Stored Mana + Total Mana Rewards`, where: +- Let `Total Mana In` be the total amount of Mana on the input side of a transaction, consisting of + `Total Potential Mana + Total Stored Mana + Total Mana Rewards`, where: - `Transaction Creation Slot` is the `Creation Slot` of the transaction, - `Output Creation Slot` is the `Creation Slot` of the output. - `Total Potential Mana` is the sum of Potential Mana for each input `i`: - - where its Potential Mana is calculcated as `Potential Mana(Generation Amount, Output Creation Slot, Transaction Creation Slot)` according to [Potential Mana](#potential-mana) where: + - where its Potential Mana is calculcated as + `Potential Mana(Generation Amount, Output Creation Slot, Transaction Creation Slot)` according to + [Potential Mana](#potential-mana) where: - `Generation Amount` is defined as `Amount_i - Min Deposit`, if `Min Deposit > Amount_i`, otherwise `0`, where: - `Amount_i` is the `Amount` of `i`, - `Min Deposit` is the minimum necessary storage deposit of `i`. - `Total Stored Mana` is the sum of Stored Mana for each input `i`: - - where its Stored Mana is calculated as `Stored Mana(Stored Mana_i, Output Creation Slot, Transaction Creation Slot)`, where: + - where its Stored Mana is calculated as + `Stored Mana(Stored Mana_i, Output Creation Slot, Transaction Creation Slot)`, where: - `Stored Mana_i` is the `Mana` of `i`. - - `Total Mana Rewards` is the sum of decayed Mana Rewards for each input referenced by a _Reward Input_ in the transaction. - - TODO: We should make a function to calculate the decayed Mana Rewards as well, even if the node usually returns the rewards already in decayed form. -- Let `Total Mana Out` be the total amount of Mana on the output side of a transaction, consisting of `Total Stored Mana + Total Allotted Mana`, where: + - `Total Mana Rewards` is the sum of decayed Mana Rewards for each input referenced by a _Reward Input_ in the + transaction. + - TODO: We should make a function to calculate the decayed Mana Rewards as well, even if the node usually returns + the rewards already in decayed form. +- Let `Total Mana Out` be the total amount of Mana on the output side of a transaction, consisting of + `Total Stored Mana + Total Allotted Mana`, where: - `Total Stored Mana` is the sum of `Mana` in each output. - `Total Allotted Mana` is the sum of `Mana` in each _Allotment_. A transaction is only valid if `Total Mana In >= Total Mana Out`. | :warning: Potential Overflows | -|-------------------------------| - -It is highly recommended to use overflow checks for arithmetic operations when calculating Mana balances to avoid over- and underflows. +| ----------------------------- | -## Lookup Table +It is highly recommended to use overflow checks for arithmetic operations when calculating Mana balances to avoid over- +and underflows. +## Lookup Table From 163ff2a1d50030c14de62fbf2ce965e5412e8e18 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Mon, 23 Oct 2023 11:56:31 +0100 Subject: [PATCH 135/157] Remove manually added Table of Contents GitHub and the Wiki both auto-generate a ToC, so it's unnecessary to maintain it. --- tips/TIP-0039/tip-0039.md | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 14ddb53b6..394c47555 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -13,32 +13,6 @@ created: 2023-05-03 requires: TIP-42 --- -# Table of Contents - -1. [Summary](#summary) -2. [Motivation](#motivation) -3. [Building Blocks](#building-blocks) - - [Data Types \& Subschema Notation](#data-types--subschema-notation) - - [Protocol Parameters](#protocol-parameters) -4. [Mana design](#mana-design) - - [Mana Burn](#mana-burn) - - [Reference Mana Cost](#reference-mana-cost) - - [Mana Decay](#mana-decay) - - [Mana Decay Parameters](#mana-decay-parameters) - - [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics) - - [How to use the lookup table](#how-to-use-the-lookup-table) - - [Potential Mana](#potential-mana) - - [Potential Mana Semantic Validation](#potential-mana-semantic-validation) - - [Stored Mana](#stored-mana) - - [Stored Mana Semantic Validation](#stored-mana-semantic-validation) - - [Block Issuance Credit](#block-issuance-credit) - - [Block Issuance Credit Semantic Validation](#block-issuance-credit-semantic-validation) - - [Mana rewards](#mana-rewards) - - [Mana Rewards Semantic Validation](#mana-rewards-semantic-validation) - - [Mana Transaction Validation Rules](#mana-transaction-validation-rules) - - [Lookup Table](#lookup-table) -5. [Copyright](#copyright) - # Summary This document defines the Mana-related concepts and the Mana dynamics in the IOTA 2.0 protocol. The TIP defines the two From 5dc88f5bf3eb99b6a5d2c1931a9cd71150e0aebf Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 25 Oct 2023 15:14:17 +0100 Subject: [PATCH 136/157] Fix markdown rendering, prettify formula --- tips/TIP-0039/tip-0039.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 394c47555..9787541b1 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -305,8 +305,9 @@ defined in the last section (including the decays): ### Potential Mana Semantic Validation - The exact algorithm to calculate the Potential Mana generated by an output created at slot `slotIndexCreated` and -consumed at slot `slotIndexTarget` (which has an epoch `consumptionEpoch`), holding `amount` IOTA coins, is given by -`ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)`, where + consumed at slot `slotIndexTarget` (which has an epoch `consumptionEpoch`), holding `amount` IOTA coins, is given by + `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)`, where +
Lookup Table: Decays for Mana in decay index granularity scaled to 232
@@ -450,16 +451,19 @@ validators and delegators with Mana is reasonable as it does not extract value f - Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or delegated. - Mana rewards must be put on outputs as stored Mana on the output side of the transaction. -- The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: - Let - `reward`, `rewardEpoch`, and `claimingSlotEpoch` be as follows:
Name
- - -
Name TypeDescription
reward uint64 The amount of Mana rewards available to be - claimed for staking or delegation for a specific epoch.
rewardEpoch uint64 The - index of the epoch for which Mana rewards are claimed.
claimingSlotEpoch uint64 The epoch of the slot in which the Mana rewards are claimed.
- - Let `n = claimingSlotEpoch - rewardEpoch`. If `n > 0`, with the aid of the [lookup table](#lookup-table) and the algorithm - defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the - rewards by applying `reward = decay(reward, n)`. - If `n = 0`, the amount to be put on outputs is the entire `reward`. +- The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: + - Let `n = Claiming Slot Epoch - Reward Epoch`. + - If `n > 0`, with the aid of the [lookup table](#lookup-table) and the algorithm defined in section + [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the rewards by applying + `Reward = decay(Reward, n)`. + - If `n = 0`, the amount to be put on outputs is the entire `Reward`. + - Let `Reward`, `Reward Epoch`, and `Claiming Slot Epoch` be defined as follows: + +| Name | Type | Description | +| ------------------- | ------ | -------------------------------------------------------------------------------------------------- | +| Reward | uint64 | The amount of Mana rewards available to be claimed for staking or delegation for a specific epoch. | +| Reward Epoch | uint64 | The index of the epoch for which Mana rewards are claimed. | +| Claiming Slot Epoch | uint64 | The epoch of the slot in which the Mana rewards are claimed. | ## Mana Transaction Validation Rules From b8ea21d0b7b425aead5198b44596b8da1810ad09 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 25 Oct 2023 15:17:38 +0100 Subject: [PATCH 137/157] Add Can Burn Mana TX capabilit flag rule --- tips/TIP-0039/tip-0039.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 9787541b1..ca1b2873d 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -491,7 +491,10 @@ validators and delegators with Mana is reasonable as it does not extract value f - `Total Stored Mana` is the sum of `Mana` in each output. - `Total Allotted Mana` is the sum of `Mana` in each _Allotment_. -A transaction is only valid if `Total Mana In >= Total Mana Out`. +A transaction is only valid if either of the following conditions holds: + +- `Total Mana In == Total Mana Out`. +- `Total Mana In > Total Mana Out` and the _Can Burn Mana_ Flag in the _Transaction Capabilities_ is **set**. | :warning: Potential Overflows | | ----------------------------- | From a5a5e2d342af33c4c9c1bcb4b3a313d6d0151bbe Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Fri, 27 Oct 2023 13:11:59 +0100 Subject: [PATCH 138/157] Prettify Potential Mana calculation --- tips/TIP-0039/tip-0039.md | 145 ++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 86 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index ca1b2873d..c6e0bed82 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -177,15 +177,16 @@ table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch E ### How to use the lookup table -In this section, we define a function `decay(value, epochIndexDiff)`, that decays an amount of Mana `value` by the +In this section, we define a function `Decay(value, epochIndexDiff)`, that decays an amount of Mana `value` by the factor relative to `epochIndexDiff` epochs. Note that the table `Decay Factors` defined above only gives the values of decays factors for up to `Decay Factors Length` epochs. To calculate the decay for larger periods of time, we combine values defined in the [lookup table](#lookup-table) for other numbers smaller than `Decay Factors Length`, using an algorithm that will be defined below. First, we define three auxiliary functions: -- Let `upperBits(value, n)` be: given a uint64 integer `value`, returns its upper `n` bits -- Let `lowerBits(value, n)` be: given a uint64 integer `value`, returns its lower `n` bits -- `MultiplicationAndShift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the result +- Let `Upper Bits(value, n)` be: given a uint64 integer `value`, returns its upper `n` bits +- Let `Lower Bits(value, n)` be: given a uint64 integer `value`, returns its lower `n` bits +- `Multiplication And Shift(valueHi, valueLo, multFactor, shiftFactor)`: the goal of this function is to return the + result - of a multiplication of a uint64 by a uint32, shifted `shiftFactor` times to the right, whenever this result is smaller - than 264. To do so, it uses the following algorithm: - Let `valueHi` and `valueLo` be the upper and lower 32 bits of an integer smaller than 264, @@ -195,9 +196,9 @@ algorithm that will be defined below. First, we define three auxiliary functions shift. - Then compute `valueHi = valueHi * multFactor`. - Then compute - `valueLo = lowerBits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor`. - - Then compute `valueHi = (valueHi >> shiftFactor) + upperBits(valueLo, 32)`. - - Then compute `valueLo = lowerBits(valueLo, 32)`. + `valueLo = Lower Bits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor`. + - Then compute `valueHi = (valueHi >> shiftFactor) + Upper Bits(valueLo, 32)`. + - Then compute `valueLo = Lower Bits(valueLo, 32)`. - Return `valueHi, valueLo`, representing the upper 32 and the lower 32 bits, respectively, of the result. With the functions above defined, we proceed to define the `decay` function that takes as input a uint64 value `value` @@ -205,16 +206,16 @@ and decays it by the correct decay factor relative to `epochIndexDiff` epochs. O `Decay Factors(epochIndexDiff)` denotes the value of the table relative to `epochIndexDiff` epochs, which not necessarily corresponds to the `epochIndexDiff`th entry of the table. -- Let `decay(value, epochIndexDiff)` be: +- Let `Decay(value, epochIndexDiff)` be: - If `value == 0` or `epochIndexDiff == 0`, return `value`. - Else: - - Let `valueHi = upperBits(value, 32)` and `valueLo = lowerBits(value, 32)`. + - Let `valueHi = Upper Bits(value, 32)` and `valueLo = Lower Bits(value, 32)`. - Let `m` and `n` be natural numbers such that `m + n * Decay Factors Length = epochIndexDiff`, and `m < Decay Factors Length`. - Apply - `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(Decay Factors Length), Decay Factors Exponent)` + `valueHi, valueLo = Multiplication And Shift(valueHi, valueLo, Decay Factors(Decay Factors Length), Decay Factors Exponent)` `n` times. - - Apply `valueHi, valueLo = MultiplicationAndShift(valueHi, valueLo, Decay Factors(m), Decay Factors Exponent)` + - Apply `valueHi, valueLo = Multiplication And Shift(valueHi, valueLo, Decay Factors(m), Decay Factors Exponent)` once. - The function should return `valueHi, valueLo` combined into a single `uint64`, i.e., it returns `valueHi << 32 + valueLo`. @@ -269,73 +270,45 @@ parameter `γ` is then represented as `Generation Rate`*2-`Generation `Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. For additional explanations about these approximations, see the Incentives Whitepaper. -We begin by defining an auxiliary function `generateMana` that (intuitively) generates Mana without applying any type of -decay (note that we use some of the functions and constants defined in the last sections): - -- `generateMana(value,slotIndexDiff)` returns the generated mana from holding `value` tokens for `slotIndexDiff` slots, - without applying any decay: _ if `slotIndexDiff` == 0 or `Generation Rate` == 0, the function returns `0` _ otherwise, - it returns `MultiplicationAndShift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. - -Now we define the function `ManaGenerationWithDecay` that actually calculates the Potential Mana using the formulas -defined in the last section (including the decays): - -- `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)` calculates the generated potential mana by - holding `amount` tokens from `slotIndexCreated` to `slotIndexTarget` and applies the decay to the result: - - If `slotIndexCreated` ≥ `slotIndexTarget`, it returns `0`. - - Otherwise, let `epochIndexCreated` and `epochIndexTarget` be the epochs to which `slotIndexCreated` and - `slotIndexTarget` belongs to, respectively. We divide the remaining of the function into three cases: - - If `epochIndexCreated` == `epochIndexTarget`, it returns - `generateMana(amount, slotIndexTarget-slotIndexCreated)`. - - If `epochIndexCreated` == `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between - `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, and `SlotsSinceEpochStart` be the difference - between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`. Then, the function returns - `manaDecayed + manaGenerated`, where - - `manaDecayed` = `decay(generateMana(amount, SlotsBeforeNextEpoch), 1)` - - `manaGenerated` = `generateMana(amount, SlotsSinceEpochStart)` - - If `epochIndexCreated` < `epochIndexTarget`-1, let `SlotsBeforeNextEpoch` be the difference between - `slotIndexCreated` and the first slot of epoch `epochIndexCreated+1`, `SlotsSinceEpochStart` be the difference - between `slotIndexTarget` and the last slot of epoch `epochIndexTarget-1`, and `epochIndexDiff` be - `epochIndexTarget - epochIndexCreated`. Then, the function returns - `potentialMana_0 - potentialMana_n_1 + potentialMana_n`, where - - `potentialMana_n = decay(generateMana(amount, SlotsBeforeNextEpoch), epochIndexDiff)` - - `potentialMana_n_1 = decay(c, epochIndexDiff-1)` - - `potentialMana_0 = c + generateMana(amount, SlotsSinceEpochStart) - (c >> Decay Factors Exponent)` - - `c = MultiplicationAndShift(upperBits(amount, 32), lowerBits(amount, 32), Decay Factor Epochs Sum * Generation Rate , Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent)`. - -### Potential Mana Semantic Validation - -- The exact algorithm to calculate the Potential Mana generated by an output created at slot `slotIndexCreated` and - consumed at slot `slotIndexTarget` (which has an epoch `consumptionEpoch`), holding `amount` IOTA coins, is given by - `ManaGenerationWithDecay(amount, slotIndexCreated, slotIndexTarget)`, where - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
Amountuint64 - The amount of IOTA coins held in the output. -
slotIndexCreateduint64 - The index of slot in which the output was created. -
slotIndexTargetuint64 - The index of slot in which the output is consumed. -
+We begin by defining an auxiliary procedure `Generate Mana` that (intuitively) generates Mana without applying any type +of decay (note that we use some of the procedures and constants defined in the last sections): + +- `Generate Mana(value,slotIndexDiff)` returns the generated mana from holding `value` tokens for `slotIndexDiff` slots, + without applying any decay: _ if `slotIndexDiff` == 0 or `Generation Rate` == 0, the procedure returns `0` _ + otherwise, it returns `Multiplication And Shift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. + +Now we define the procedure `Potential Mana` that actually calculates the Potential Mana using the formulas defined in +the last section (including the decays): + +Let `Potential Mana(Amount, Output Creation Slot, Transaction Creation Slot)` be the procedure that calculates the +Potential Mana generated by holding `Amount` IOTA coins from `Output Creation Slot` to `Transaction Creation Slot` and +applies the decay to the result, where: + +- `Amount` is the amount of IOTA coins held in the output. +- `Output Creation Slot` is the slot index in which the output was created. +- `Transaction Creation Slot` is the slot index in which the output is consumed. +- If `Output Creation Slot ≥ Transaction Creation Slot` return `0`. +- Otherwise: + - Let `Output Creation Epoch` be the epoch to which `Output Creation Slot` belongs. + - Let `Transaction Creation Epoch` be the epoch to which `Transaction Creation Slot` belongs. + - See [TIP-46 (Time)](TIP-0046/tip-0046.md#time) for the conversion procedure. + - If `Output Creation Epoch == Transaction Creation Epoch`: + - Return `Generate Mana(Amount, Transaction Creation Slot - Output Creation Slot)`. + - Let `Slots Before Next Epoch` be the difference between `Output Creation Slot` and the first slot of epoch + `Output Creation Epoch + 1`. + - Let `Slots Since Epoch Start` be the difference between `Transaction Creation Slot` and the last slot of epoch + `Transaction Creation Epoch - 1`. + - If `Output Creation Epoch == Transaction Creation Epoch - 1`: + - Return `Mana Decayed + Mana Generated`, where + - `Mana Decayed = Decay(Generate Mana(Amount, Slots Before Next Epoch), 1)` + - `Mana Generated = Generate Mana(Amount, Slots Since Epoch Start)` + - If `Output Creation Epoch < Transaction Creation Epoch - 1`: + - Let `Epoch Index Diff` be `Transaction Creation Epoch - Output Creation Epoch`. + - Return `Potential Mana_0 - Potential Mana_n_1 + Potential Mana_n`, where + - `Potential Mana_n = Decay(Generate Mana(Amount, Slots Before Next Epoch), Epoch Index Diff)` + - `Potential Mana_n_1 = Decay(c, Epoch Index Diff - 1)` + - `Potential Mana_0 = c + Generate Mana(Amount, Slots Since Epoch Start) - (c >> Decay Factors Exponent)` + - `c = Multiplication And Shift(Upper Bits(Amount, 32), Lower Bits(Amount, 32), Decay Factor Epochs Sum * Generation Rate , Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent)`. ## Stored Mana @@ -383,7 +356,7 @@ output with stored Mana. -The algorithm to decay the stored Mana is as follows: +The algorithm to decay the Stored Mana is as follows: ```go creationEpoch = epoch(creationSlot) @@ -391,7 +364,7 @@ consumptionEpoch = epoch(consumptionSlot) if creationEpoch == consumptionEpoch: newManaAmount = manaAmount else: - newManaAmount = decay(manaAmount, consumptionEpoch - creationEpoch) + newManaAmount = Decay(manaAmount, consumptionEpoch - creationEpoch) ``` ## Block Issuance Credit @@ -434,7 +407,7 @@ TODO: This function doesn't take into account the last time the BIC was decayed ```go if BIC > 0: - new_BIC = decay(BIC, 1) + new_BIC = Decay(BIC, 1) else: new_BIC = BIC ``` @@ -455,7 +428,7 @@ validators and delegators with Mana is reasonable as it does not extract value f - Let `n = Claiming Slot Epoch - Reward Epoch`. - If `n > 0`, with the aid of the [lookup table](#lookup-table) and the algorithm defined in section [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the rewards by applying - `Reward = decay(Reward, n)`. + `Reward = Decay(Reward, n)`. - If `n = 0`, the amount to be put on outputs is the entire `Reward`. - Let `Reward`, `Reward Epoch`, and `Claiming Slot Epoch` be defined as follows: @@ -470,7 +443,7 @@ validators and delegators with Mana is reasonable as it does not extract value f - Let `Total Mana In` be the total amount of Mana on the input side of a transaction, consisting of `Total Potential Mana + Total Stored Mana + Total Mana Rewards`, where: - `Transaction Creation Slot` is the `Creation Slot` of the transaction, - - `Output Creation Slot` is the `Creation Slot` of the output. + - `Output Creation Slot` is the `Creation Slot` of the transaction that created the output. - `Total Potential Mana` is the sum of Potential Mana for each input `i`: - where its Potential Mana is calculcated as `Potential Mana(Generation Amount, Output Creation Slot, Transaction Creation Slot)` according to @@ -488,8 +461,8 @@ validators and delegators with Mana is reasonable as it does not extract value f the rewards already in decayed form. - Let `Total Mana Out` be the total amount of Mana on the output side of a transaction, consisting of `Total Stored Mana + Total Allotted Mana`, where: - - `Total Stored Mana` is the sum of `Mana` in each output. - - `Total Allotted Mana` is the sum of `Mana` in each _Allotment_. + - `Total Stored Mana` is the sum of `Mana` fields for each output. + - `Total Allotted Mana` is the sum of `Mana` fields for each _Allotment_. A transaction is only valid if either of the following conditions holds: @@ -509,7 +482,7 @@ and underflows. n Type - decay(n) + Decay(n) 1 From fe7705d02e58ceeefcceee9d39dddc1dfad6a924 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Fri, 27 Oct 2023 18:29:30 +0100 Subject: [PATCH 139/157] Prettify Stored Mana calculation --- tips/TIP-0039/tip-0039.md | 67 ++++++++++----------------------------- 1 file changed, 17 insertions(+), 50 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c6e0bed82..c6d7373c0 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -66,7 +66,7 @@ It is an essential element of the IOTA protocol, as it is used: - [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana that can be used to issue blocks. During a transaction, Stored or Potential Mana can be _allotted_ which moves the Mana off the UTXO ledger and converts it to BIC. Only this form of Mana be used to issue blocks. -- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA tokens. The Mana +- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA coins. The Mana rewarded from these activities is not registered in the UTXO ledger and must be moved to it when claiming rewards as described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). @@ -312,60 +312,27 @@ applies the decay to the result, where: ## Stored Mana -_Stored Mana_ is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA -tokens) of Mana that can be transferred within certain rules between different users, which allows for Mana market -development. +_Stored Mana_ is the main form of Mana. It is a UTXO-based form (i.e., it is contained in outputs, just like IOTA coins) +of Mana that can be transferred within certain rules between different users, which allows for the development of a Mana +market. -All output types, except Foundry and Delegation Outputs, can hold stored Mana in the _Mana_ field. This field represents +All output types, except Foundry and Delegation Outputs, can hold Stored Mana in the _Mana_ field. This field represents the amount of stored Mana at the output's creation time until the time when the output is consumed without decay applied to it. -Decay must, therefore, be applied whenever an output containing Stored Mana is consumed. The creation slot of each -output with stored Mana. - -### Stored Mana Semantic Validation - -- Stored Mana must be decayed before it is transferred into a new output as follows: - - Let `manaAmount`, `consumptionSlot`, and `creationSlot`, be - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
manaAmountuint64 - The amount of stored Mana held by the output. -
creationSlotuint64 - The index of slot in which the output was created. -
consumptionSlotuint64 - The index of slot in which the output is consumed. -
- -The algorithm to decay the Stored Mana is as follows: +Decay must, therefore, be applied whenever an output containing Stored Mana is consumed. -```go -creationEpoch = epoch(creationSlot) -consumptionEpoch = epoch(consumptionSlot) -if creationEpoch == consumptionEpoch: - newManaAmount = manaAmount -else: - newManaAmount = Decay(manaAmount, consumptionEpoch - creationEpoch) -``` +Let `Stored Mana(Mana Amount, Output Creation Slot, Transaction Creation Slot)` be the procedure that calculates the +decay whenever Stored Mana is consumed, where: + +- `Mana Amount` is the amount of Stored Mana held in an output. +- `Output Creation Slot` is the slot index in which the output was created. +- `Transaction Creation Slot` is the slot index in which the output is consumed. +- Let `Output Creation Epoch` be the epoch to which `Output Creation Slot` belongs. +- Let `Transaction Creation Epoch` be the epoch to which `Transaction Creation Slot` belongs. + - See [TIP-46 (Time)](TIP-0046/tip-0046.md#time) for the conversion procedure. +- If `Output Creation Epoch == Transaction Creation Epoch` return `Mana Amount`. +- Otherwise return `Decay(Mana Amount, Transaction Creation Epoch - Output Creation Epoch)`. ## Block Issuance Credit From 4a27f84031df462e5f352899cd862deb9198dd86 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Fri, 3 Nov 2023 11:05:02 +0100 Subject: [PATCH 140/157] Format Markdown --- tips/TIP-0039/tip-0039.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index c6d7373c0..931d1b6aa 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -263,11 +263,11 @@ Analogously, if `n=1`, Potential Mana = γSd1 exp(-βΔ) + γSd The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for -n>1, noticing that we already approximated 2`Decay Factors Exponent` exp(-βΔi) by +n>1, noticing that we already approximated 2 `Decay Factors Exponent` exp(-βΔi) by `Decay Factors(i)`, where `Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. The -parameter `γ` is then represented as `Generation Rate`*2-`Generation Rate Exponent`, and +parameter `γ` is then represented as `Generation Rate`*2-`Generation Rate Exponent`, and exp(-βΔ)/(1 - exp(-βΔ)) is approximated by -`Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. For additional explanations + `Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. For additional explanations about these approximations, see the Incentives Whitepaper. We begin by defining an auxiliary procedure `Generate Mana` that (intuitively) generates Mana without applying any type From afa7a2a7cb26fceeda1b35db77118235961bbc8a Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Tue, 28 Nov 2023 09:22:45 +0100 Subject: [PATCH 141/157] Update tips/TIP-0039/tip-0039.md Co-authored-by: DaughterOfMars --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 931d1b6aa..059ac1895 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -65,7 +65,7 @@ It is an essential element of the IOTA protocol, as it is used: one of its more explicit forms, i.e. Stored Mana or Block Issuance Credits. - [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana that can be used to issue blocks. During a transaction, Stored or Potential Mana can be _allotted_ which moves the Mana off the UTXO ledger and converts it to - BIC. Only this form of Mana be used to issue blocks. + BIC. Only this form of Mana can be used to issue blocks. - [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA coins. The Mana rewarded from these activities is not registered in the UTXO ledger and must be moved to it when claiming rewards as described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). From 06513fb33be20be1d67e7408308a00a3c53b154e Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Tue, 5 Dec 2023 13:07:15 +0100 Subject: [PATCH 142/157] Apply suggestions from code review Co-authored-by: Thibault Martinez --- tips/TIP-0039/tip-0039.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 059ac1895..14ec4e707 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -16,7 +16,7 @@ requires: TIP-42 # Summary This document defines the Mana-related concepts and the Mana dynamics in the IOTA 2.0 protocol. The TIP defines the two -types of Mana, namely **Potential Mana** and **Stored Mana,** as well as the **Block Issuance Credit (BIC)** that Mana +types of Mana, namely **Potential Mana** and **Stored Mana**, as well as the **Block Issuance Credit (BIC)** that Mana can be allotted to. # Motivation @@ -28,7 +28,7 @@ IOTA Tokenomics. The following document gives a high-level overview of Mana type change introduced in the IOTA 2.0 protocol, next to staking, delegation and congestion control changes. This document works with the Congestion Control Algorithm with Mana, in which block issuers must allot Mana to their account to increase their Block Issuance Credit balance. In order to issue a block a certain amount of BIC is deducted from the -issuer account balance and burned. In order to issue blocks and use all functionalitiy related to Mana, the user is +issuer account balance and burned. In order to issue blocks and use all functionality related to Mana, the user is required to have an account, which is introduced in [TIP-42](../TIP-0042/tip-0042.md). # Building Blocks @@ -412,7 +412,7 @@ validators and delegators with Mana is reasonable as it does not extract value f - `Transaction Creation Slot` is the `Creation Slot` of the transaction, - `Output Creation Slot` is the `Creation Slot` of the transaction that created the output. - `Total Potential Mana` is the sum of Potential Mana for each input `i`: - - where its Potential Mana is calculcated as + - where its Potential Mana is calculated as `Potential Mana(Generation Amount, Output Creation Slot, Transaction Creation Slot)` according to [Potential Mana](#potential-mana) where: - `Generation Amount` is defined as `Amount_i - Min Deposit`, if `Min Deposit > Amount_i`, otherwise `0`, where: From b5ac891887b9ab505db7d74a27d0f1119060fa6c Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 11 Dec 2023 12:26:25 +0000 Subject: [PATCH 143/157] change beta->annualdecay as "base" decay parameter --- tips/TIP-0039/tip-0039.md | 1558 +++++++++++++++++++------------------ 1 file changed, 783 insertions(+), 775 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 14ec4e707..32ec024bf 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -60,20 +60,21 @@ It is an essential element of the IOTA protocol, as it is used: - [**Stored Mana**](#stored-mana) is Mana that is stored in UTXOs and can consequently be moved on the UTXO ledger, which allows for Mana Market development. -- [**Potential Mana**](#potential-mana) is generated by holding IOTA coins. The longer the IOTA coins were unspent, the - more Potential Mana is generated. When an output is spent, its Potential Mana is released and can be transitioned to - one of its more explicit forms, i.e. Stored Mana or Block Issuance Credits. -- [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana that can be used to issue blocks. During - a transaction, Stored or Potential Mana can be _allotted_ which moves the Mana off the UTXO ledger and converts it to - BIC. Only this form of Mana can be used to issue blocks. -- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA coins. The Mana - rewarded from these activities is not registered in the UTXO ledger and must be moved to it when claiming rewards as - described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). +- [**Potential Mana**](#potential-mana) is generated by holding IOTA coins. + The longer the IOTA coins were unspent, the more Potential Mana is generated. + When an output is spent, its Potential Mana is released and can be transitioned to one of its more explicit forms, i.e. Stored Mana or Block Issuance Credits. + Note that the Potential Mana is a quatity not explicitly tracked in the ledger state, but easily derived from it. +- [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana used as an anti-spam mechanism to the block issuance process. + During a transaction, Stored or Potential Mana can be _allotted as BIC_, which moves the Mana off the UTXO ledger and converts it to Block Issuance Credits. + Only this form of Mana can be burnt to issue blocks. +- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA coins. + The Mana rewarded from these activities is not registered automatically in the UTXO ledger; thus, rewards must be claimed, as described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). + +The **Mana holdings** of a user are the sum of all the Potential Mana and Stored Mana in their Account Output that they use to issue blocks. ## Mana Burn -The **Mana holdings** of a user are the sum of all the Potential Mana and Stored Mana (but not the Mana Rewards) in -their Account Output that they use to issue blocks. According to the congestion control mechanism, during each block +According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a certain amount of Mana dictated by the work score of the block and the Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Users who overspend Mana (i.e., try to issue more blocks than their Mana Holdings allow) will have their account locked until @@ -81,22 +82,22 @@ their debt is paid. ### Reference Mana Cost -_Reference Mana Cost (RMC)_ is used to decide how much Mana should be burned from BIC by each block in that slot. RMC is -computed according to an algorithm based on recent traffic activity: the algorithm counts the number of blocks in slots -that are _Maximum Committable Age (MCA)_ slots in the past so that all nodes agree on that value of RMC and know this -value in advance (before issuing the block). +The _Reference Mana Cost (RMC)_ of a slot is used to decide how much Mana should be burned from the user's BIC each time a block is issued in that slot. +The RMC is computed according to an algorithm based on the recent traffic activity. +Note that the algorithm takes as in input the number of blocks in certain slots older than _Maximum Committable Age (MCA)_, meaning that all nodes know and agree on the RMC of a slot in advance (even before issuing the block). From a high-level perspective, the RMC algorithm works as follows: - If the number of blocks in slot `i - MCA` is larger than a given threshold, then the RMC increases. -- Otherwise, if the activity is low, the RMC decreases. -- The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes - too large for the majority of users, and activity drops. +- Otherwise (i.e., if the activity is low), the RMC decreases. +- The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes too large for the majority of users, and activity drops. (TO DO: update with the final price dynamic design) + +To limit fluctuations in the RMC, it is recommended +to update its value at least every MCA slots. The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid price -manipulations by malicious actors. Note that blocks from issuers with negative BIC balances are excluded with respect to -the RMC calculation, but they do make part of the slot commitment. To limit fluctuations in the RMC, it is recommended -to update its value every MCA slot at least. +manipulations by malicious actors. Note that even though blocks from issuers with negative BIC balances are excluded with respect to +the RMC calculation, they do make part of the slot commitment. ## Mana Decay @@ -106,8 +107,10 @@ non-gameability (e.g., splitting accounts or other behaviors that are not helpfu the fairness of Mana, the same global decay factor needs to be applied to all the above-mentioned forms of Mana. As the exact formulas in which the decay factor will be applied might differ among the Mana types, it is essential to -point out that all of them are based on the same exponential decay with the same parameter `β`. The Incentives -Whitepaper (TODO: Link) provides the specific formula for the decay function in Appendix A. +point out that all of them are based on the same exponential decay with the same parameter `β`. The [Incentives +Whitepaper](https://files.iota.org/papers/IOTA_2.0_Incentives_And_Tokenomics_Whitepaper.pdf) provides the specific formula for the decay function in Appendix A. +To make the formulas and code more intuitive, we define in this TIP an `Annual Decay` multiplicative factor that is mathematically equivalent to the decay mechanism introduced in the Whitepaper. +This new parameter is defined such that `Annual Decay = exp(-β)`. Applying decay for the generation of new Mana and staking rewards is conceptually straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO @@ -115,7 +118,7 @@ spending. In any of those cases, the node must calculate the decay based on epoc 2Slots Per Epoch Exponent slots, the epoch changes, meaning that every set of consecutive 2Slots Per Epoch Exponent slots will be in the same epoch. -The decay parameter `β` (together with the Mana generation parameter `Mana Structure::Generation Rate`) was set so the +The decay parameter `Annual Decay` (together with the Mana generation parameter `Mana Structure::Generation Rate`) was set so the maximum theoretical Mana in the system is smaller than 2Bits Count - 1, where `Bits Count` refers to the `Mana Structure::Bits Count` protocol parameter. This means that, even though Mana is stored as a uint64, it effectively uses less than 64 bits (in the case of BIC, it uses at most `Bits Count + 1` bits, `Bits Count` for the @@ -127,7 +130,7 @@ unreasonably large value in practice to avoid overflowing of the variables even ### Mana Decay Parameters The tables below describe the key parameters used for the Mana decay calculations in the next sections of this TIP. -Notice that the parameters in the first table are only used in the explanations in this TIP, but not in the code. +Notice that the parameters in the first table are only used in the explanations in this TIP, but not explicitly in the code. @@ -135,9 +138,9 @@ Notice that the parameters in the first table are only used in the explanations - + @@ -156,6 +159,13 @@ Notice that the parameters in the first table are only used in the explanations Additionally, we use the protocol parameters, as defined in [TIP-49], and `Decay Factors Length`, defined as the length of the lookup Table `Decay Factors`. +We also use an auxiliary `Decay per Epoch` factor, derived from `Annual Decay` and other protocol parameters using the following relation: + +Decay per Epoch = Annual Decay(Seconds per Epoch/Seconds per Year) + +where +- `Seconds per Year = 60*60*24*365` +- Seconds per Epoch = Slot Duration In Seconds * 2Slots Per Epoch Exponent ## Mana and fixed point arithmetics @@ -171,9 +181,9 @@ point arithmetics. In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of 2Decay Factors -Exponentexp(-βΔn), for different values of `n` ranging from 1 to `Decay Factors Length`. For the lookup +ExponentDecay per Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. For the lookup table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, -`Slot Duration in Seconds` = 10, (which implies that `Δ = 0.002597666159`), and `β = 1/3` per year. +`Slot Duration in Seconds` = 10, and `Annual Decay` = 0,7. ### How to use the lookup table @@ -222,11 +232,7 @@ necessarily corresponds to the `epochIndexDiff`th entry of the table. Other implementations of the functions above are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and -multiplications with integers might lead to different results when the order is altered. Example: suppose one needs to -calculate 1002 * 99 / 100 *21 / 100. Following the left-to-right order, this would result in 1002 _ 99 / 100 _ 21 / 100 -= 99198 / 100 _ 21 / 100 = 991 _ 21 / 100 = 20811 / 100 = 208. If someone did this operation in a different order, let's -say 1002 _ 21 / 100 _ 99 / 100, the result would be 1002 _ 21 / 100 _ 99 / 100 = 21042 / 100 _ 99 / 100 = 210 _ 99 / 100 -= 20790 / 100 = 207. +multiplications with integers variables might lead to different results when the order is altered. ## Potential Mana @@ -238,7 +244,7 @@ transaction that created the UTXO. ### Rationale behind the Potential Mana formulas We model the potential Mana generated by an output holding `S` IOTA coins as the combination of a fixed generation per -slot `γS` and a decay equivalent to a multiplication by exp(-βΔ) every time an epoch ends. +slot `γS` and a decay equivalent to a multiplication by Decay per Epoch every time an epoch ends. ![](./img/slots_potential_mana-2.png) @@ -248,34 +254,36 @@ decayed `n` times. The Mana generated in epoch `i+1` "crosses" n-1 decay boundar and so on, until the Mana generated in epoch `j`, which is not decayed at all. Adding these values, we find the following formulas (where d is the number of slots in an epoch): -Potential Mana = γSd1 exp(-βΔn) + ΣγSd exp(-βΔi) + γSd2, where the summation is over +Potential Mana = γSd1 Decay per Epochn + ΣγSd Decay per Epochi + γSd2, where the summation is over i = 1,...,n-1. Solving the sum, this results: -Potential Mana = γSd1 exp(-βΔn) + γSd2 + γSd exp(-βΔ) (1 - exp(-βΔ(n-1))) / -(1-exp(-βΔ)), +Potential Mana = γSd1 Decay per Epochn + γSd2 + γSd Decay per Epoch (1 - Decay per Epochn-1) / +(1-Decay per Epoch), -Analogously, if `n=1`, Potential Mana = γSd1 exp(-βΔ) + γSd2; if `n=0`, +Analogously, if `n=1`, Potential Mana = γSd1 Decay per Epoch + γSd2; if `n=0`, Potential Mana = γSδ, where δ is the difference between the creation and consumption slots. ### Potential Mana formulas with fixed point arithmetics The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for -n>1, noticing that we already approximated 2 `Decay Factors Exponent` exp(-βΔi) by +n>1, noticing that we already approximated 2 `Decay Factors Exponent` Decay per Epochi by `Decay Factors(i)`, where `Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. The parameter `γ` is then represented as `Generation Rate`*2-`Generation Rate Exponent`, and -exp(-βΔ)/(1 - exp(-βΔ)) is approximated by +Decay per Epoch/(1 - Decay per Epoch) is approximated by `Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. For additional explanations -about these approximations, see the Incentives Whitepaper. +about these approximations, see the [Incentives +Whitepaper](https://files.iota.org/papers/IOTA_2.0_Incentives_And_Tokenomics_Whitepaper.pdf). We begin by defining an auxiliary procedure `Generate Mana` that (intuitively) generates Mana without applying any type of decay (note that we use some of the procedures and constants defined in the last sections): - `Generate Mana(value,slotIndexDiff)` returns the generated mana from holding `value` tokens for `slotIndexDiff` slots, - without applying any decay: _ if `slotIndexDiff` == 0 or `Generation Rate` == 0, the procedure returns `0` _ - otherwise, it returns `Multiplication And Shift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. + without applying any decay: + - if `slotIndexDiff` == 0 or `Generation Rate` == 0, the procedure returns `0` + - otherwise, it returns `Multiplication And Shift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. Now we define the procedure `Potential Mana` that actually calculates the Potential Mana using the formulas defined in the last section (including the decays): @@ -445,7 +453,7 @@ and underflows. ## Lookup Table
Description
βAnnual Decay - Global exponential decay parameter. + Global annual decay parameter.
- + @@ -453,1828 +461,1828 @@ and underflows. - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + +
Lookup Table: Decays for Mana in decay index granularity scaled to 232Lookup Table: Decays for Mana in epoch granularity scaled to 232
n Type
1 - uint32 4291249941 uint32 4290989755
2 - uint32 4287535805 uint32 4287015898
3 - uint32 4283824883 uint32 4283045721
4 - uint32 4280117173 uint32 4279079221
5 - uint32 4276412671 uint32 4275116394
6 - uint32 4272711377 uint32 4271157237
7 - uint32 4269013285 uint32 4267201747
8 - uint32 4265318395 uint32 4263249920
9 - uint32 4261626702 uint32 4259301752
10 - uint32 4257938205 uint32 4255357241
11 - uint32 4254252900 uint32 4251416383
12 - uint32 4250570785 uint32 4247479175
13 - uint32 4246891856 uint32 4243545613
14 - uint32 4243216112 uint32 4239615693
15 - uint32 4239543550 uint32 4235689414
16 - uint32 4235874166 uint32 4231766770
17 - uint32 4232207957 uint32 4227847759
18 - uint32 4228544922 uint32 4223932377
19 - uint32 4224885058 uint32 4220020622
20 - uint32 4221228361 uint32 4216112489
21 - uint32 4217574829 uint32 4212207975
22 - uint32 4213924459 uint32 4208307077
23 - uint32 4210277249 uint32 4204409792
24 - uint32 4206633195 uint32 4200516116
25 - uint32 4202992295 uint32 4196626046
26 - uint32 4199354547 uint32 4192739579
27 - uint32 4195719947 uint32 4188856710
28 - uint32 4192088493 uint32 4184977438
29 - uint32 4188460182 uint32 4181101758
30 - uint32 4184835011 uint32 4177229668
31 - uint32 4181212978 uint32 4173361163
32 - uint32 4177594080 uint32 4169496241
33 - uint32 4173978314 uint32 4165634898
34 - uint32 4170365677 uint32 4161777132
35 - uint32 4166756168 uint32 4157922938
36 - uint32 4163149782 uint32 4154072313
37 - uint32 4159546518 uint32 4150225254
38 - uint32 4155946372 uint32 4146381758
39 - uint32 4152349343 uint32 4142541822
40 - uint32 4148755427 uint32 4138705441
41 - uint32 4145164621 uint32 4134872614
42 - uint32 4141576923 uint32 4131043336
43 - uint32 4137992331 uint32 4127217604
44 - uint32 4134410840 uint32 4123395415
45 - uint32 4130832450 uint32 4119576766
46 - uint32 4127257157 uint32 4115761654
47 - uint32 4123684959 uint32 4111950074
48 - uint32 4120115852 uint32 4108142024
49 - uint32 4116549834 uint32 4104337501
50 - uint32 4112986903 uint32 4100536502
51 - uint32 4109427055 uint32 4096739022
52 - uint32 4105870289 uint32 4092945060
53 - uint32 4102316601 uint32 4089154610
54 - uint32 4098765988 uint32 4085367672
55 - uint32 4095218449 uint32 4081584240
56 - uint32 4091673981 uint32 4077804312
57 - uint32 4088132580 uint32 4074027884
58 - uint32 4084594244 uint32 4070254954
59 - uint32 4081058971 uint32 4066485518
60 - uint32 4077526757 uint32 4062719573
61 - uint32 4073997601 uint32 4058957115
62 - uint32 4070471499 uint32 4055198142
63 - uint32 4066948449 uint32 4051442650
64 - uint32 4063428449 uint32 4047690636
65 - uint32 4059911495 uint32 4043942097
66 - uint32 4056397585 uint32 4040197029
67 - uint32 4052886716 uint32 4036455429
68 - uint32 4049378886 uint32 4032717295
69 - uint32 4045874092 uint32 4028982622
70 - uint32 4042372332 uint32 4025251408
71 - uint32 4038873602 uint32 4021523650
72 - uint32 4035377901 uint32 4017799344
73 - uint32 4031885225 uint32 4014078486
74 - uint32 4028395572 uint32 4010361075
75 - uint32 4024908939 uint32 4006647106
76 - uint32 4021425325 uint32 4002936577
77 - uint32 4017944725 uint32 3999229484
78 - uint32 4014467138 uint32 3995525824
79 - uint32 4010992560 uint32 3991825594
80 - uint32 4007520990 uint32 3988128791
81 - uint32 4004052425 uint32 3984435412
82 - uint32 4000586862 uint32 3980745453
83 - uint32 3997124298 uint32 3977058911
84 - uint32 3993664731 uint32 3973375783
85 - uint32 3990208159 uint32 3969696066
86 - uint32 3986754578 uint32 3966019757
87 - uint32 3983303986 uint32 3962346853
88 - uint32 3979856381 uint32 3958677350
89 - uint32 3976411760 uint32 3955011245
90 - uint32 3972970120 uint32 3951348535
91 - uint32 3969531459 uint32 3947689218
92 - uint32 3966095774 uint32 3944033289
93 - uint32 3962663063 uint32 3940380746
94 - uint32 3959233323 uint32 3936731586
95 - uint32 3955806551 uint32 3933085805
96 - uint32 3952382745 uint32 3929443400
97 - uint32 3948961903 uint32 3925804369
98 - uint32 3945544021 uint32 3922168708
99 - uint32 3942129098 uint32 3918536413
100 - uint32 3938717130 uint32 3914907483
101 - uint32 3935308116 uint32 3911281913
102 - uint32 3931902052 uint32 3907659701
103 - uint32 3928498936 uint32 3904040843
104 - uint32 3925098765 uint32 3900425337
105 - uint32 3921701537 uint32 3896813179
106 - uint32 3918307250 uint32 3893204366
107 - uint32 3914915900 uint32 3889598896
108 - uint32 3911527486 uint32 3885996764
109 - uint32 3908142004 uint32 3882397968
110 - uint32 3904759453 uint32 3878802505
111 - uint32 3901379829 uint32 3875210372
112 - uint32 3898003131 uint32 3871621566
113 - uint32 3894629355 uint32 3868036083
114 - uint32 3891258499 uint32 3864453920
115 - uint32 3887890560 uint32 3860875075
116 - uint32 3884525537 uint32 3857299544
117 - uint32 3881163426 uint32 3853727325
118 - uint32 3877804224 uint32 3850158414
119 - uint32 3874447931 uint32 3846592808
120 - uint32 3871094542 uint32 3843030504
121 - uint32 3867744056 uint32 3839471499
122 - uint32 3864396469 uint32 3835915790
123 - uint32 3861051780 uint32 3832363374
124 - uint32 3857709986 uint32 3828814248
125 - uint32 3854371084 uint32 3825268408
126 - uint32 3851035072 uint32 3821725853
127 - uint32 3847701948 uint32 3818186578
128 - uint32 3844371708 uint32 3814650580
129 - uint32 3841044351 uint32 3811117858
130 - uint32 3837719873 uint32 3807588407
131 - uint32 3834398273 uint32 3804062225
132 - uint32 3831079548 uint32 3800539308
133 - uint32 3827763695 uint32 3797019654
134 - uint32 3824450713 uint32 3793503259
135 - uint32 3821140597 uint32 3789990121
136 - uint32 3817833347 uint32 3786480237
137 - uint32 3814528959 uint32 3782973602
138 - uint32 3811227431 uint32 3779470216
139 - uint32 3807928760 uint32 3775970074
140 - uint32 3804632945 uint32 3772473173
141 - uint32 3801339982 uint32 3768979511
142 - uint32 3798049869 uint32 3765489084
143 - uint32 3794762604 uint32 3762001889
144 - uint32 3791478184 uint32 3758517924
145 - uint32 3788196607 uint32 3755037186
146 - uint32 3784917870 uint32 3751559671
147 - uint32 3781641970 uint32 3748085377
148 - uint32 3778368907 uint32 3744614300
149 - uint32 3775098676 uint32 3741146437
150 - uint32 3771831275 uint32 3737681787
151 - uint32 3768566702 uint32 3734220344
152 - uint32 3765304955 uint32 3730762108
153 - uint32 3762046031 uint32 3727307074
154 - uint32 3758789928 uint32 3723855240
155 - uint32 3755536643 uint32 3720406602
156 - uint32 3752286174 uint32 3716961158
157 - uint32 3749038518 uint32 3713518905
158 - uint32 3745793673 uint32 3710079840
159 - uint32 3742551636 uint32 3706643960
160 - uint32 3739312405 uint32 3703211262
161 - uint32 3736075978 uint32 3699781742
162 - uint32 3732842352 uint32 3696355399
163 - uint32 3729611525 uint32 3692932229
164 - uint32 3726383494 uint32 3689512229
165 - uint32 3723158258 uint32 3686095396
166 - uint32 3719935812 uint32 3682681728
167 - uint32 3716716156 uint32 3679271221
168 - uint32 3713499286 uint32 3675863872
169 - uint32 3710285201 uint32 3672459679
170 - uint32 3707073897 uint32 3669058639
171 - uint32 3703865373 uint32 3665660748
172 - uint32 3700659626 uint32 3662266004
173 - uint32 3697456653 uint32 3658874404
174 - uint32 3694256453 uint32 3655485944
175 - uint32 3691059023 uint32 3652100623
176 - uint32 3687864360 uint32 3648718437
177 - uint32 3684672462 uint32 3645339383
178 - uint32 3681483326 uint32 3641963459
179 - uint32 3678296951 uint32 3638590661
180 - uint32 3675113334 uint32 3635220986
181 - uint32 3671932472 uint32 3631854432
182 - uint32 3668754363 uint32 3628490996
183 - uint32 3665579005 uint32 3625130675
184 - uint32 3662406395 uint32 3621773465
185 - uint32 3659236531 uint32 3618419365
186 - uint32 3656069411 uint32 3615068371
187 - uint32 3652905032 uint32 3611720480
188 - uint32 3649743392 uint32 3608375690
189 - uint32 3646584488 uint32 3605033997
190 - uint32 3643428318 uint32 3601695399
191 - uint32 3640274880 uint32 3598359893
192 - uint32 3637124172 uint32 3595027476
193 - uint32 3633976190 uint32 3591698145
194 - uint32 3630830933 uint32 3588371897
195 - uint32 3627688398 uint32 3585048730
196 - uint32 3624548583 uint32 3581728640
197 - uint32 3621411486 uint32 3578411625
198 - uint32 3618277104 uint32 3575097682
199 - uint32 3615145434 uint32 3571786808
200 - uint32 3612016476 uint32 3568479000
201 - uint32 3608890225 uint32 3565174255
202 - uint32 3605766680 uint32 3561872571
203 - uint32 3602645839 uint32 3558573944
204 - uint32 3599527699 uint32 3555278373
205 - uint32 3596412257 uint32 3551985853
206 - uint32 3593299512 uint32 3548696383
207 - uint32 3590189461 uint32 3545409959
208 - uint32 3587082102 uint32 3542126578
209 - uint32 3583977433 uint32 3538846238
210 - uint32 3580875450 uint32 3535568936
211 - uint32 3577776153 uint32 3532294669
212 - uint32 3574679537 uint32 3529023435
213 - uint32 3571585602 uint32 3525755230
214 - uint32 3568494345 uint32 3522490051
215 - uint32 3565405764 uint32 3519227897
216 - uint32 3562319855 uint32 3515968763
217 - uint32 3559236618 uint32 3512712648
218 - uint32 3556156049 uint32 3509459548
219 - uint32 3553078146 uint32 3506209461
220 - uint32 3550002907 uint32 3502962384
221 - uint32 3546930330 uint32 3499718314
222 - uint32 3543860413 uint32 3496477248
223 - uint32 3540793152 uint32 3493239183
224 - uint32 3537728546 uint32 3490004118
225 - uint32 3534666593 uint32 3486772048
226 - uint32 3531607290 uint32 3483542972
227 - uint32 3528550634 uint32 3480316886
228 - uint32 3525496624 uint32 3477093788
229 - uint32 3522445258 uint32 3473873674
230 - uint32 3519396533 uint32 3470656543
231 - uint32 3516350446 uint32 3467442391
232 - uint32 3513306995 uint32 3464231216
233 - uint32 3510266179 uint32 3461023014
234 - uint32 3507227995 uint32 3457817784
235 - uint32 3504192440 uint32 3454615522
236 - uint32 3501159513 uint32 3451416225
237 - uint32 3498129210 uint32 3448219892
238 - uint32 3495101531 uint32 3445026518
239 - uint32 3492076472 uint32 3441836102
240 - uint32 3489054031 uint32 3438648641
241 - uint32 3486034206 uint32 3435464131
242 - uint32 3483016995 uint32 3432282571
243 - uint32 3480002395 uint32 3429103957
244 - uint32 3476990404 uint32 3425928286
245 - uint32 3473981020 uint32 3422755557
246 - uint32 3470974241 uint32 3419585766
247 - uint32 3467970065 uint32 3416418910
248 - uint32 3464968488 uint32 3413254987
249 - uint32 3461969510 uint32 3410093995
250 - uint32 3458973127 uint32 3406935929
251 - uint32 3455979337 uint32 3403780789
252 - uint32 3452988139 uint32 3400628570
253 - uint32 3449999530 uint32 3397479270
254 - uint32 3447013507 uint32 3394332887
255 - uint32 3444030069 uint32 3391189418
256 - uint32 3441049213 uint32 3388048860
257 - uint32 3438070937 uint32 3384911211
258 - uint32 3435095238 uint32 3381776467
259 - uint32 3432122115 uint32 3378644627
260 - uint32 3429151566 uint32 3375515686
261 - uint32 3426183587 uint32 3372389644
262 - uint32 3423218178 uint32 3369266496
263 - uint32 3420255335 uint32 3366146241
264 - uint32 3417295056 uint32 3363028875
265 - uint32 3414337339 uint32 3359914396
266 - uint32 3411382183 uint32 3356802802
267 - uint32 3408429584 uint32 3353694089
268 - uint32 3405479541 uint32 3350588256
269 - uint32 3402532051 uint32 3347485298
270 - uint32 3399587112 uint32 3344385214
271 - uint32 3396644722 uint32 3341288001
272 - uint32 3393704878 uint32 3338193657
273 - uint32 3390767579 uint32 3335102178
274 - uint32 3387832823 uint32 3332013562
275 - uint32 3384900606 uint32 3328927806
276 - uint32 3381970927 uint32 3325844909
277 - uint32 3379043784 uint32 3322764866
278 - uint32 3376119175 uint32 3319687675
279 - uint32 3373197097 uint32 3316613335
280 - uint32 3370277548 uint32 3313541841
281 - uint32 3367360525 uint32 3310473192
282 - uint32 3364446028 uint32 3307407385
283 - uint32 3361534053 uint32 3304344417
284 - uint32 3358624598 uint32 3301284286
285 - uint32 3355717662 uint32 3298226988
286 - uint32 3352813241 uint32 3295172522
287 - uint32 3349911335 uint32 3292120885
288 - uint32 3347011940 uint32 3289072074
289 - uint32 3344115054 uint32 3286026086
290 - uint32 3341220676 uint32 3282982919
291 - uint32 3338328803 uint32 3279942570
292 - uint32 3335439433 uint32 3276905037
293 - uint32 3332552563 uint32 3273870317
294 - uint32 3329668193 uint32 3270838408
295 - uint32 3326786318 uint32 3267809306
296 - uint32 3323906939 uint32 3264783010
297 - uint32 3321030051 uint32 3261759516
298 - uint32 3318155653 uint32 3258738822
299 - uint32 3315283743 uint32 3255720926
300 - uint32 3312414319 uint32 3252705824
301 - uint32 3309547378 uint32 3249693515
302 - uint32 3306682918 uint32 3246683996
303 - uint32 3303820938 uint32 3243677263
304 - uint32 3300961435 uint32 3240673315
305 - uint32 3298104407 uint32 3237672149
306 - uint32 3295249852 uint32 3234673763
307 - uint32 3292397767 uint32 3231678153
308 - uint32 3289548151 uint32 3228685317
309 - uint32 3286701001 uint32 3225695253
310 - uint32 3283856315 uint32 3222707958
311 - uint32 3281014092 uint32 3219723430
312 - uint32 3278174328 uint32 3216741666
313 - uint32 3275337023 uint32 3213762662
314 - uint32 3272502173 uint32 3210786418
315 - uint32 3269669777 uint32 3207812930
316 - uint32 3266839832 uint32 3204842196
317 - uint32 3264012336 uint32 3201874213
318 - uint32 3261187288 uint32 3198908979
319 - uint32 3258364685 uint32 3195946490
320 - uint32 3255544525 uint32 3192986746
321 - uint32 3252726806 uint32 3190029742
322 - uint32 3249911526 uint32 3187075477
323 - uint32 3247098682 uint32 3184123947
324 - uint32 3244288273 uint32 3181175151
325 - uint32 3241480296 uint32 3178229086
326 - uint32 3238674749 uint32 3175285749
327 - uint32 3235871631 uint32 3172345138
328 - uint32 3233070939 uint32 3169407251
329 - uint32 3230272671 uint32 3166472084
330 - uint32 3227476825 uint32 3163539635
331 - uint32 3224683399 uint32 3160609902
332 - uint32 3221892391 uint32 3157682882
333 - uint32 3219103798 uint32 3154758573
334 - uint32 3216317619 uint32 3151836972
335 - uint32 3213533851 uint32 3148918077
336 - uint32 3210752492 uint32 3146001885
337 - uint32 3207973541 uint32 3143088393
338 - uint32 3205196995 uint32 3140177600
339 - uint32 3202422853 uint32 3137269503
340 - uint32 3199651111 uint32 3134364098
341 - uint32 3196881768 uint32 3131461384
342 - uint32 3194114823 uint32 3128561359
343 - uint32 3191350272 uint32 3125664019
344 - uint32 3188588114 uint32 3122769362
345 - uint32 3185828346 uint32 3119877387
346 - uint32 3183070967 uint32 3116988089
347 - uint32 3180315975 uint32 3114101467
348 - uint32 3177563367 uint32 3111217518
349 - uint32 3174813142 uint32 3108336240
350 - uint32 3172065297 uint32 3105457631
351 - uint32 3169319830 uint32 3102581687
352 - uint32 3166576739 uint32 3099708407
353 - uint32 3163836023 uint32 3096837788
354 - uint32 3161097679 uint32 3093969827
355 - uint32 3158361705 uint32 3091104522
356 - uint32 3155628099 uint32 3088241871
357 - uint32 3152896859 uint32 3085381870
358 - uint32 3150167982 uint32 3082524519
359 - uint32 3147441468 uint32 3079669813
360 - uint32 3144717314 uint32 3076817752
361 - uint32 3141995517 uint32 3073968331
362 - uint32 3139276076 uint32 3071121550
363 - uint32 3136558989 uint32 3068277404
364 - uint32 3133844253 uint32 3065435893
365 - uint32 3131131867 uint32 3062597013
From 2fc5ee75c7a0e7c7442227a019820a132f35a819 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 13 Dec 2023 16:32:33 +0100 Subject: [PATCH 144/157] Format Markdown --- tips/TIP-0039/tip-0039.md | 115 ++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 53 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 32ec024bf..3896d0dd7 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -60,44 +60,47 @@ It is an essential element of the IOTA protocol, as it is used: - [**Stored Mana**](#stored-mana) is Mana that is stored in UTXOs and can consequently be moved on the UTXO ledger, which allows for Mana Market development. -- [**Potential Mana**](#potential-mana) is generated by holding IOTA coins. - The longer the IOTA coins were unspent, the more Potential Mana is generated. - When an output is spent, its Potential Mana is released and can be transitioned to one of its more explicit forms, i.e. Stored Mana or Block Issuance Credits. - Note that the Potential Mana is a quatity not explicitly tracked in the ledger state, but easily derived from it. -- [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana used as an anti-spam mechanism to the block issuance process. - During a transaction, Stored or Potential Mana can be _allotted as BIC_, which moves the Mana off the UTXO ledger and converts it to Block Issuance Credits. - Only this form of Mana can be burnt to issue blocks. -- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA coins. - The Mana rewarded from these activities is not registered automatically in the UTXO ledger; thus, rewards must be claimed, as described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). - -The **Mana holdings** of a user are the sum of all the Potential Mana and Stored Mana in their Account Output that they use to issue blocks. +- [**Potential Mana**](#potential-mana) is generated by holding IOTA coins.\ + The longer the IOTA coins were unspent, the more Potential Mana is generated. When an output is spent, its Potential + Mana is released and can be transitioned to one of its more explicit forms, i.e. Stored Mana or Block Issuance + Credits. Note that the Potential Mana is a quatity not explicitly tracked in the ledger state, but easily derived from + it. +- [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana used as an anti-spam mechanism to the + block issuance process. During a transaction, Stored or Potential Mana can be _allotted as BIC_, which moves the Mana + off the UTXO ledger and converts it to Block Issuance Credits. Only this form of Mana can be burnt to issue blocks. +- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA coins. The Mana + rewarded from these activities is not registered automatically in the UTXO ledger; thus, rewards must be claimed, as + described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). + +The **Mana holdings** of a user are the sum of all the Potential Mana and Stored Mana in their Account Output that they +use to issue blocks. ## Mana Burn -According to the congestion control mechanism, during each block -issuance, the block issuer needs to burn a certain amount of Mana dictated by the work score of the block and the -Reference Mana Cost (RMC). The Mana burned by the block is subtracted from the block issuer's BIC balance. Users who -overspend Mana (i.e., try to issue more blocks than their Mana Holdings allow) will have their account locked until -their debt is paid. +According to the congestion control mechanism, during each block issuance, the block issuer needs to burn a certain +amount of Mana dictated by the work score of the block and the Reference Mana Cost (RMC). The Mana burned by the block +is subtracted from the block issuer's BIC balance. Users who overspend Mana (i.e., try to issue more blocks than their +Mana Holdings allow) will have their account locked until their debt is paid. ### Reference Mana Cost -The _Reference Mana Cost (RMC)_ of a slot is used to decide how much Mana should be burned from the user's BIC each time a block is issued in that slot. -The RMC is computed according to an algorithm based on the recent traffic activity. -Note that the algorithm takes as in input the number of blocks in certain slots older than _Maximum Committable Age (MCA)_, meaning that all nodes know and agree on the RMC of a slot in advance (even before issuing the block). +The _Reference Mana Cost (RMC)_ of a slot is used to decide how much Mana should be burned from the user's BIC each time +a block is issued in that slot. The RMC is computed according to an algorithm based on the recent traffic activity. Note +that the algorithm takes as in input the number of blocks in certain slots older than _Maximum Committable Age (MCA)_, +meaning that all nodes know and agree on the RMC of a slot in advance (even before issuing the block). From a high-level perspective, the RMC algorithm works as follows: - If the number of blocks in slot `i - MCA` is larger than a given threshold, then the RMC increases. - Otherwise (i.e., if the activity is low), the RMC decreases. -- The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes too large for the majority of users, and activity drops. (TO DO: update with the final price dynamic design) +- The rate at which the RMC decreases is higher than its increase to tackle situations where the price suddenly becomes + too large for the majority of users, and activity drops. (TO DO: update with the final price dynamic design) -To limit fluctuations in the RMC, it is recommended -to update its value at least every MCA slots. +To limit fluctuations in the RMC, it is recommended to update its value at least every MCA slots. The RMC update only takes into account the blocks issued by accounts having non-negative BIC balances to avoid price -manipulations by malicious actors. Note that even though blocks from issuers with negative BIC balances are excluded with respect to -the RMC calculation, they do make part of the slot commitment. +manipulations by malicious actors. Note that even though blocks from issuers with negative BIC balances are excluded +with respect to the RMC calculation, they do make part of the slot commitment. ## Mana Decay @@ -107,10 +110,11 @@ non-gameability (e.g., splitting accounts or other behaviors that are not helpfu the fairness of Mana, the same global decay factor needs to be applied to all the above-mentioned forms of Mana. As the exact formulas in which the decay factor will be applied might differ among the Mana types, it is essential to -point out that all of them are based on the same exponential decay with the same parameter `β`. The [Incentives -Whitepaper](https://files.iota.org/papers/IOTA_2.0_Incentives_And_Tokenomics_Whitepaper.pdf) provides the specific formula for the decay function in Appendix A. -To make the formulas and code more intuitive, we define in this TIP an `Annual Decay` multiplicative factor that is mathematically equivalent to the decay mechanism introduced in the Whitepaper. -This new parameter is defined such that `Annual Decay = exp(-β)`. +point out that all of them are based on the same exponential decay with the same parameter `β`. The +[Incentives Whitepaper](https://files.iota.org/papers/IOTA_2.0_Incentives_And_Tokenomics_Whitepaper.pdf) provides the +specific formula for the decay function in Appendix A. To make the formulas and code more intuitive, we define in this +TIP an `Annual Decay` multiplicative factor that is mathematically equivalent to the decay mechanism introduced in the +Whitepaper. This new parameter is defined such that `Annual Decay = exp(-β)`. Applying decay for the generation of new Mana and staking rewards is conceptually straightforward since it is done at the time of storing this Mana. Similarly, applying the decay on the already stored Mana happens during the UTXO @@ -118,19 +122,21 @@ spending. In any of those cases, the node must calculate the decay based on epoc 2Slots Per Epoch Exponent slots, the epoch changes, meaning that every set of consecutive 2Slots Per Epoch Exponent slots will be in the same epoch. -The decay parameter `Annual Decay` (together with the Mana generation parameter `Mana Structure::Generation Rate`) was set so the -maximum theoretical Mana in the system is smaller than 2Bits Count - 1, where `Bits Count` -refers to the `Mana Structure::Bits Count` protocol parameter. This means that, even though Mana is stored as a uint64, -it effectively uses less than 64 bits (in the case of BIC, it uses at most `Bits Count + 1` bits, `Bits Count` for the -value and one for the sign). Note that the system will almost certainly never use all the `Bits Count` to store Mana -since, for the Mana supply to get to this value, nobody can spend their Mana for years. In practice, we expect to work -with Mana values way smaller than 2Bits Count - 1; however, we must count on what would be an -unreasonably large value in practice to avoid overflowing of the variables even if with a minimal probability. +The decay parameter `Annual Decay` (together with the Mana generation parameter `Mana Structure::Generation Rate`) was +set so the maximum theoretical Mana in the system is smaller than 2Bits Count - 1, where +`Bits Count` refers to the `Mana Structure::Bits Count` protocol parameter. This means that, even though Mana is stored +as a uint64, it effectively uses less than 64 bits (in the case of BIC, it uses at most `Bits Count + 1` bits, +`Bits Count` for the value and one for the sign). Note that the system will almost certainly never use all the +`Bits Count` to store Mana since, for the Mana supply to get to this value, nobody can spend their Mana for years. In +practice, we expect to work with Mana values way smaller than 2Bits Count - 1; however, we must +count on what would be an unreasonably large value in practice to avoid overflowing of the variables even if with a +minimal probability. ### Mana Decay Parameters The tables below describe the key parameters used for the Mana decay calculations in the next sections of this TIP. -Notice that the parameters in the first table are only used in the explanations in this TIP, but not explicitly in the code. +Notice that the parameters in the first table are only used in the explanations in this TIP, but not explicitly in the +code. @@ -158,12 +164,13 @@ Notice that the parameters in the first table are only used in the explanations
Additionally, we use the protocol parameters, as defined in [TIP-49], and `Decay Factors Length`, defined as the length -of the lookup Table `Decay Factors`. -We also use an auxiliary `Decay per Epoch` factor, derived from `Annual Decay` and other protocol parameters using the following relation: +of the lookup Table `Decay Factors`. We also use an auxiliary `Decay per Epoch` factor, derived from `Annual Decay` and +other protocol parameters using the following relation: Decay per Epoch = Annual Decay(Seconds per Epoch/Seconds per Year) where + - `Seconds per Year = 60*60*24*365` - Seconds per Epoch = Slot Duration In Seconds * 2Slots Per Epoch Exponent @@ -181,8 +188,8 @@ point arithmetics. In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of 2Decay Factors -ExponentDecay per Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. For the lookup -table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, +Exponent
Decay per Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. +For the lookup table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, `Slot Duration in Seconds` = 10, and `Annual Decay` = 0,7. ### How to use the lookup table @@ -232,7 +239,7 @@ necessarily corresponds to the `epochIndexDiff`th entry of the table. Other implementations of the functions above are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and -multiplications with integers variables might lead to different results when the order is altered. +multiplications with integers variables might lead to different results when the order is altered. ## Potential Mana @@ -254,13 +261,14 @@ decayed `n` times. The Mana generated in epoch `i+1` "crosses" n-1 decay boundar and so on, until the Mana generated in epoch `j`, which is not decayed at all. Adding these values, we find the following formulas (where d is the number of slots in an epoch): -Potential Mana = γSd1 Decay per Epochn + ΣγSd Decay per Epochi + γSd2, where the summation is over +Potential Mana = γSd1 Decay per Epochn + ΣγSd Decay per Epochi + +γSd2, where the summation is over i = 1,...,n-1. Solving the sum, this results: -Potential Mana = γSd1 Decay per Epochn + γSd2 + γSd Decay per Epoch (1 - Decay per Epochn-1) / -(1-Decay per Epoch), +Potential Mana = γSd1 Decay per Epochn + γSd2 + γSd Decay per Epoch (1 - Decay +per Epochn-1) / (1-Decay per Epoch), Analogously, if `n=1`, Potential Mana = γSd1 Decay per Epoch + γSd2; if `n=0`, Potential Mana = γSδ, where δ is the difference between the creation and consumption slots. @@ -269,21 +277,22 @@ Analogously, if `n=1`, Potential Mana = γSd1 Decay per Epoch + The formulas found in the last section are the exact formulas for the model proposed. However, we must not use floating point arithmetics, so these formulas must be adapted for the implementation. We begin by rearranging the formula for -n>1, noticing that we already approximated 2 `Decay Factors Exponent` Decay per Epochi by -`Decay Factors(i)`, where `Decay Factors Exponent` is the precision of the [lookup table](#lookup-table) used. The -parameter `γ` is then represented as `Generation Rate`*2-`Generation Rate Exponent`, and +n>1, noticing that we already approximated 2 `Decay Factors Exponent` Decay per +Epochi by `Decay Factors(i)`, where `Decay Factors Exponent` is the precision of the +[lookup table](#lookup-table) used. The parameter `γ` is then represented as +`Generation Rate`*2-`Generation Rate Exponent`, and Decay per Epoch/(1 - Decay per Epoch) is approximated by `Decay Factor Epochs Sum`*2-`Decay Factor Epochs Sum Exponent`. For additional explanations -about these approximations, see the [Incentives -Whitepaper](https://files.iota.org/papers/IOTA_2.0_Incentives_And_Tokenomics_Whitepaper.pdf). +about these approximations, see the +[Incentives Whitepaper](https://files.iota.org/papers/IOTA_2.0_Incentives_And_Tokenomics_Whitepaper.pdf). We begin by defining an auxiliary procedure `Generate Mana` that (intuitively) generates Mana without applying any type of decay (note that we use some of the procedures and constants defined in the last sections): - `Generate Mana(value,slotIndexDiff)` returns the generated mana from holding `value` tokens for `slotIndexDiff` slots, - without applying any decay: - - if `slotIndexDiff` == 0 or `Generation Rate` == 0, the procedure returns `0` - - otherwise, it returns `Multiplication And Shift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. + without applying any decay: + - if `slotIndexDiff` == 0 or `Generation Rate` == 0, the procedure returns `0` + - otherwise, it returns `Multiplication And Shift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. Now we define the procedure `Potential Mana` that actually calculates the Potential Mana using the formulas defined in the last section (including the decays): From 6627114868e0b63235cf2130718a072c2cc7f183 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 13 Dec 2023 16:33:38 +0100 Subject: [PATCH 145/157] Rename Decay function section --- tips/TIP-0039/tip-0039.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 3896d0dd7..f4f5705bb 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -192,7 +192,7 @@ ExponentDecay per Epochn, for different values of `n` ra For the lookup table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, `Slot Duration in Seconds` = 10, and `Annual Decay` = 0,7. -### How to use the lookup table +### Decay Function In this section, we define a function `Decay(value, epochIndexDiff)`, that decays an amount of Mana `value` by the factor relative to `epochIndexDiff` epochs. Note that the table `Decay Factors` defined above only gives the values of @@ -218,7 +218,7 @@ algorithm that will be defined below. First, we define three auxiliary functions - Then compute `valueLo = Lower Bits(valueLo, 32)`. - Return `valueHi, valueLo`, representing the upper 32 and the lower 32 bits, respectively, of the result. -With the functions above defined, we proceed to define the `decay` function that takes as input a uint64 value `value` +With the functions above defined, we proceed to define the `Decay` function that takes as input a uint64 value `value` and decays it by the correct decay factor relative to `epochIndexDiff` epochs. OBS: note that here, `Decay Factors(epochIndexDiff)` denotes the value of the table relative to `epochIndexDiff` epochs, which not necessarily corresponds to the `epochIndexDiff`th entry of the table. From 5f93f2ac007da6de570bf4c7f85fa0324605215e Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Thu, 14 Dec 2023 14:20:36 +0100 Subject: [PATCH 146/157] Rm outdated Mana Rewards section, update tx rules --- tips/TIP-0039/tip-0039.md | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index f4f5705bb..08af433aa 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -396,32 +396,6 @@ else: new_BIC = BIC ``` -## Mana rewards - -_Mana rewards_ are used to reward for participation in staking for validation and delegating IOTA coins. Rewarding -validators and delegators with Mana is reasonable as it does not extract value from other IOTA coin holders. - -### Mana Rewards Semantic Validation - -- Mana rewards must be calculated on a per-epoch basis. -- Mana rewards must become available for claiming when the last slot of the epoch is committed to. -- Mana rewards must be claimed by creating a transaction that consumes the original outputs that were staked or - delegated. -- Mana rewards must be put on outputs as stored Mana on the output side of the transaction. -- The decay must be applied to Mana rewards before they are put on outputs according to the following algorithm: - - Let `n = Claiming Slot Epoch - Reward Epoch`. - - If `n > 0`, with the aid of the [lookup table](#lookup-table) and the algorithm defined in section - [Mana and fixed point arithmetics](#mana-and-fixed-point-arithmetics), we must now decay the rewards by applying - `Reward = Decay(Reward, n)`. - - If `n = 0`, the amount to be put on outputs is the entire `Reward`. - - Let `Reward`, `Reward Epoch`, and `Claiming Slot Epoch` be defined as follows: - -| Name | Type | Description | -| ------------------- | ------ | -------------------------------------------------------------------------------------------------- | -| Reward | uint64 | The amount of Mana rewards available to be claimed for staking or delegation for a specific epoch. | -| Reward Epoch | uint64 | The index of the epoch for which Mana rewards are claimed. | -| Claiming Slot Epoch | uint64 | The epoch of the slot in which the Mana rewards are claimed. | - ## Mana Transaction Validation Rules - Let `Total Mana In` be the total amount of Mana on the input side of a transaction, consisting of @@ -439,10 +413,12 @@ validators and delegators with Mana is reasonable as it does not extract value f - where its Stored Mana is calculated as `Stored Mana(Stored Mana_i, Output Creation Slot, Transaction Creation Slot)`, where: - `Stored Mana_i` is the `Mana` of `i`. - - `Total Mana Rewards` is the sum of decayed Mana Rewards for each input referenced by a _Reward Input_ in the - transaction. - - TODO: We should make a function to calculate the decayed Mana Rewards as well, even if the node usually returns - the rewards already in decayed form. + - `Total Mana Rewards` is the sum of total claimable rewards from each input referenced by a _Reward Input_ in the + transaction, each of which is calculated as follows: + - If the pointee of the _Reward Input_ is an _Account Output_ with its `Account ID`, the rewards are calculated with + [`Validator Rewards(Account ID)`](../TIP-0040/tip-0040.md#validator-rewards). + - If the pointee of the _Reward Input_ is a _Delegation Output_ with its `Delegation ID`, the rewards are calculated + with [`Delegation Rewards(Delegation ID)`](../TIP-0040/tip-0040.md#delegator-rewards). - Let `Total Mana Out` be the total amount of Mana on the output side of a transaction, consisting of `Total Stored Mana + Total Allotted Mana`, where: - `Total Stored Mana` is the sum of `Mana` fields for each output. From cfca2bc15984242448477f5216cb8a6e2b7d1acd Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Thu, 14 Dec 2023 14:48:39 +0100 Subject: [PATCH 147/157] Remove pre-calculated lookup table --- tips/TIP-0039/tip-0039.md | 1849 +------------------------------------ 1 file changed, 9 insertions(+), 1840 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 08af433aa..0d66cabdd 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -164,7 +164,7 @@ code. Additionally, we use the protocol parameters, as defined in [TIP-49], and `Decay Factors Length`, defined as the length -of the lookup Table `Decay Factors`. We also use an auxiliary `Decay per Epoch` factor, derived from `Annual Decay` and +of the lookup table `Decay Factors`. We also use an auxiliary `Decay per Epoch` factor, derived from `Annual Decay` and other protocol parameters using the following relation: Decay per Epoch = Annual Decay(Seconds per Epoch/Seconds per Year) @@ -185,12 +185,8 @@ point arithmetics (which do not expose the nodes to these rounding divergencies) require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. -In the last section of this TIP, we introduce a lookup table that will be used in the rest of this TIP (and possibly -other TIPs), as a tool to perform calculations that would otherwise be done with floating point operations. -Specifically, the [lookup table](#lookup-table) introduced is an integer approximation of 2Decay Factors -ExponentDecay per Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. -For the lookup table in this document, we set `Decay Factors Exponent` = 32, `Slots Per Epoch Exponent` = 13, -`Slot Duration in Seconds` = 10, and `Annual Decay` = 0,7. +In the [lookup table](#lookup-table) section of this TIP, a lookup table is introduced that will be used in the rest of +this TIP, as a tool to perform calculations that would otherwise be done with floating point operations. ### Decay Function @@ -437,1839 +433,12 @@ and underflows. ## Lookup Table - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lookup Table: Decays for Mana in epoch granularity scaled to 232
nTypeDecay(n)
1 - uint32 4290989755
2 - uint32 4287015898
3 - uint32 4283045721
4 - uint32 4279079221
5 - uint32 4275116394
6 - uint32 4271157237
7 - uint32 4267201747
8 - uint32 4263249920
9 - uint32 4259301752
10 - uint32 4255357241
11 - uint32 4251416383
12 - uint32 4247479175
13 - uint32 4243545613
14 - uint32 4239615693
15 - uint32 4235689414
16 - uint32 4231766770
17 - uint32 4227847759
18 - uint32 4223932377
19 - uint32 4220020622
20 - uint32 4216112489
21 - uint32 4212207975
22 - uint32 4208307077
23 - uint32 4204409792
24 - uint32 4200516116
25 - uint32 4196626046
26 - uint32 4192739579
27 - uint32 4188856710
28 - uint32 4184977438
29 - uint32 4181101758
30 - uint32 4177229668
31 - uint32 4173361163
32 - uint32 4169496241
33 - uint32 4165634898
34 - uint32 4161777132
35 - uint32 4157922938
36 - uint32 4154072313
37 - uint32 4150225254
38 - uint32 4146381758
39 - uint32 4142541822
40 - uint32 4138705441
41 - uint32 4134872614
42 - uint32 4131043336
43 - uint32 4127217604
44 - uint32 4123395415
45 - uint32 4119576766
46 - uint32 4115761654
47 - uint32 4111950074
48 - uint32 4108142024
49 - uint32 4104337501
50 - uint32 4100536502
51 - uint32 4096739022
52 - uint32 4092945060
53 - uint32 4089154610
54 - uint32 4085367672
55 - uint32 4081584240
56 - uint32 4077804312
57 - uint32 4074027884
58 - uint32 4070254954
59 - uint32 4066485518
60 - uint32 4062719573
61 - uint32 4058957115
62 - uint32 4055198142
63 - uint32 4051442650
64 - uint32 4047690636
65 - uint32 4043942097
66 - uint32 4040197029
67 - uint32 4036455429
68 - uint32 4032717295
69 - uint32 4028982622
70 - uint32 4025251408
71 - uint32 4021523650
72 - uint32 4017799344
73 - uint32 4014078486
74 - uint32 4010361075
75 - uint32 4006647106
76 - uint32 4002936577
77 - uint32 3999229484
78 - uint32 3995525824
79 - uint32 3991825594
80 - uint32 3988128791
81 - uint32 3984435412
82 - uint32 3980745453
83 - uint32 3977058911
84 - uint32 3973375783
85 - uint32 3969696066
86 - uint32 3966019757
87 - uint32 3962346853
88 - uint32 3958677350
89 - uint32 3955011245
90 - uint32 3951348535
91 - uint32 3947689218
92 - uint32 3944033289
93 - uint32 3940380746
94 - uint32 3936731586
95 - uint32 3933085805
96 - uint32 3929443400
97 - uint32 3925804369
98 - uint32 3922168708
99 - uint32 3918536413
100 - uint32 3914907483
101 - uint32 3911281913
102 - uint32 3907659701
103 - uint32 3904040843
104 - uint32 3900425337
105 - uint32 3896813179
106 - uint32 3893204366
107 - uint32 3889598896
108 - uint32 3885996764
109 - uint32 3882397968
110 - uint32 3878802505
111 - uint32 3875210372
112 - uint32 3871621566
113 - uint32 3868036083
114 - uint32 3864453920
115 - uint32 3860875075
116 - uint32 3857299544
117 - uint32 3853727325
118 - uint32 3850158414
119 - uint32 3846592808
120 - uint32 3843030504
121 - uint32 3839471499
122 - uint32 3835915790
123 - uint32 3832363374
124 - uint32 3828814248
125 - uint32 3825268408
126 - uint32 3821725853
127 - uint32 3818186578
128 - uint32 3814650580
129 - uint32 3811117858
130 - uint32 3807588407
131 - uint32 3804062225
132 - uint32 3800539308
133 - uint32 3797019654
134 - uint32 3793503259
135 - uint32 3789990121
136 - uint32 3786480237
137 - uint32 3782973602
138 - uint32 3779470216
139 - uint32 3775970074
140 - uint32 3772473173
141 - uint32 3768979511
142 - uint32 3765489084
143 - uint32 3762001889
144 - uint32 3758517924
145 - uint32 3755037186
146 - uint32 3751559671
147 - uint32 3748085377
148 - uint32 3744614300
149 - uint32 3741146437
150 - uint32 3737681787
151 - uint32 3734220344
152 - uint32 3730762108
153 - uint32 3727307074
154 - uint32 3723855240
155 - uint32 3720406602
156 - uint32 3716961158
157 - uint32 3713518905
158 - uint32 3710079840
159 - uint32 3706643960
160 - uint32 3703211262
161 - uint32 3699781742
162 - uint32 3696355399
163 - uint32 3692932229
164 - uint32 3689512229
165 - uint32 3686095396
166 - uint32 3682681728
167 - uint32 3679271221
168 - uint32 3675863872
169 - uint32 3672459679
170 - uint32 3669058639
171 - uint32 3665660748
172 - uint32 3662266004
173 - uint32 3658874404
174 - uint32 3655485944
175 - uint32 3652100623
176 - uint32 3648718437
177 - uint32 3645339383
178 - uint32 3641963459
179 - uint32 3638590661
180 - uint32 3635220986
181 - uint32 3631854432
182 - uint32 3628490996
183 - uint32 3625130675
184 - uint32 3621773465
185 - uint32 3618419365
186 - uint32 3615068371
187 - uint32 3611720480
188 - uint32 3608375690
189 - uint32 3605033997
190 - uint32 3601695399
191 - uint32 3598359893
192 - uint32 3595027476
193 - uint32 3591698145
194 - uint32 3588371897
195 - uint32 3585048730
196 - uint32 3581728640
197 - uint32 3578411625
198 - uint32 3575097682
199 - uint32 3571786808
200 - uint32 3568479000
201 - uint32 3565174255
202 - uint32 3561872571
203 - uint32 3558573944
204 - uint32 3555278373
205 - uint32 3551985853
206 - uint32 3548696383
207 - uint32 3545409959
208 - uint32 3542126578
209 - uint32 3538846238
210 - uint32 3535568936
211 - uint32 3532294669
212 - uint32 3529023435
213 - uint32 3525755230
214 - uint32 3522490051
215 - uint32 3519227897
216 - uint32 3515968763
217 - uint32 3512712648
218 - uint32 3509459548
219 - uint32 3506209461
220 - uint32 3502962384
221 - uint32 3499718314
222 - uint32 3496477248
223 - uint32 3493239183
224 - uint32 3490004118
225 - uint32 3486772048
226 - uint32 3483542972
227 - uint32 3480316886
228 - uint32 3477093788
229 - uint32 3473873674
230 - uint32 3470656543
231 - uint32 3467442391
232 - uint32 3464231216
233 - uint32 3461023014
234 - uint32 3457817784
235 - uint32 3454615522
236 - uint32 3451416225
237 - uint32 3448219892
238 - uint32 3445026518
239 - uint32 3441836102
240 - uint32 3438648641
241 - uint32 3435464131
242 - uint32 3432282571
243 - uint32 3429103957
244 - uint32 3425928286
245 - uint32 3422755557
246 - uint32 3419585766
247 - uint32 3416418910
248 - uint32 3413254987
249 - uint32 3410093995
250 - uint32 3406935929
251 - uint32 3403780789
252 - uint32 3400628570
253 - uint32 3397479270
254 - uint32 3394332887
255 - uint32 3391189418
256 - uint32 3388048860
257 - uint32 3384911211
258 - uint32 3381776467
259 - uint32 3378644627
260 - uint32 3375515686
261 - uint32 3372389644
262 - uint32 3369266496
263 - uint32 3366146241
264 - uint32 3363028875
265 - uint32 3359914396
266 - uint32 3356802802
267 - uint32 3353694089
268 - uint32 3350588256
269 - uint32 3347485298
270 - uint32 3344385214
271 - uint32 3341288001
272 - uint32 3338193657
273 - uint32 3335102178
274 - uint32 3332013562
275 - uint32 3328927806
276 - uint32 3325844909
277 - uint32 3322764866
278 - uint32 3319687675
279 - uint32 3316613335
280 - uint32 3313541841
281 - uint32 3310473192
282 - uint32 3307407385
283 - uint32 3304344417
284 - uint32 3301284286
285 - uint32 3298226988
286 - uint32 3295172522
287 - uint32 3292120885
288 - uint32 3289072074
289 - uint32 3286026086
290 - uint32 3282982919
291 - uint32 3279942570
292 - uint32 3276905037
293 - uint32 3273870317
294 - uint32 3270838408
295 - uint32 3267809306
296 - uint32 3264783010
297 - uint32 3261759516
298 - uint32 3258738822
299 - uint32 3255720926
300 - uint32 3252705824
301 - uint32 3249693515
302 - uint32 3246683996
303 - uint32 3243677263
304 - uint32 3240673315
305 - uint32 3237672149
306 - uint32 3234673763
307 - uint32 3231678153
308 - uint32 3228685317
309 - uint32 3225695253
310 - uint32 3222707958
311 - uint32 3219723430
312 - uint32 3216741666
313 - uint32 3213762662
314 - uint32 3210786418
315 - uint32 3207812930
316 - uint32 3204842196
317 - uint32 3201874213
318 - uint32 3198908979
319 - uint32 3195946490
320 - uint32 3192986746
321 - uint32 3190029742
322 - uint32 3187075477
323 - uint32 3184123947
324 - uint32 3181175151
325 - uint32 3178229086
326 - uint32 3175285749
327 - uint32 3172345138
328 - uint32 3169407251
329 - uint32 3166472084
330 - uint32 3163539635
331 - uint32 3160609902
332 - uint32 3157682882
333 - uint32 3154758573
334 - uint32 3151836972
335 - uint32 3148918077
336 - uint32 3146001885
337 - uint32 3143088393
338 - uint32 3140177600
339 - uint32 3137269503
340 - uint32 3134364098
341 - uint32 3131461384
342 - uint32 3128561359
343 - uint32 3125664019
344 - uint32 3122769362
345 - uint32 3119877387
346 - uint32 3116988089
347 - uint32 3114101467
348 - uint32 3111217518
349 - uint32 3108336240
350 - uint32 3105457631
351 - uint32 3102581687
352 - uint32 3099708407
353 - uint32 3096837788
354 - uint32 3093969827
355 - uint32 3091104522
356 - uint32 3088241871
357 - uint32 3085381870
358 - uint32 3082524519
359 - uint32 3079669813
360 - uint32 3076817752
361 - uint32 3073968331
362 - uint32 3071121550
363 - uint32 3068277404
364 - uint32 3065435893
365 - uint32 3062597013
+The derivation of the `Mana Parameters::Decay Factors` protocol parameter, also referred to as the _lookup table_ is +described in the following section. This parameter must be calculated exactly once for a network's protocol parameters +to avoid differences in floating point operations on different machines. + +This lookup table is an integer approximation of 2Decay Factors ExponentDecay per +Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. # Copyright From 7123d72bfa5f0121b0ec5001ef2b40b1a8d84d37 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Tue, 19 Dec 2023 09:05:48 +0100 Subject: [PATCH 148/157] Update tips/TIP-0039/tip-0039.md Co-authored-by: Thibault Martinez --- tips/TIP-0039/tip-0039.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 0d66cabdd..ec5b6d47c 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -63,7 +63,7 @@ It is an essential element of the IOTA protocol, as it is used: - [**Potential Mana**](#potential-mana) is generated by holding IOTA coins.\ The longer the IOTA coins were unspent, the more Potential Mana is generated. When an output is spent, its Potential Mana is released and can be transitioned to one of its more explicit forms, i.e. Stored Mana or Block Issuance - Credits. Note that the Potential Mana is a quatity not explicitly tracked in the ledger state, but easily derived from + Credits. Note that the Potential Mana is a quantity not explicitly tracked in the ledger state, but easily derived from it. - [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana used as an anti-spam mechanism to the block issuance process. During a transaction, Stored or Potential Mana can be _allotted as BIC_, which moves the Mana From a4247f9dedde9690c9653bd4917e6c7190df0606 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Wed, 10 Jan 2024 16:31:18 +0100 Subject: [PATCH 149/157] Fix typo; invert min deposit <-> amount condiiton --- tips/TIP-0039/tip-0039.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index ec5b6d47c..dc4dc44cb 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -63,8 +63,8 @@ It is an essential element of the IOTA protocol, as it is used: - [**Potential Mana**](#potential-mana) is generated by holding IOTA coins.\ The longer the IOTA coins were unspent, the more Potential Mana is generated. When an output is spent, its Potential Mana is released and can be transitioned to one of its more explicit forms, i.e. Stored Mana or Block Issuance - Credits. Note that the Potential Mana is a quantity not explicitly tracked in the ledger state, but easily derived from - it. + Credits. Note that the Potential Mana is a quantity not explicitly tracked in the ledger state, but easily derived + from it. - [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana used as an anti-spam mechanism to the block issuance process. During a transaction, Stored or Potential Mana can be _allotted as BIC_, which moves the Mana off the UTXO ledger and converts it to Block Issuance Credits. Only this form of Mana can be burnt to issue blocks. @@ -239,7 +239,7 @@ multiplications with integers variables might lead to different results when the ## Potential Mana -_Potential Mana_ is form of Mana generated from IOTA coins over time. Every IOTA coin (besides storage deposits) +_Potential Mana_ is a form of Mana generated from IOTA coins over time. Every IOTA coin (besides storage deposits) generates potential Mana. The view on the potential Mana value can be deterministically derived from the UTXO ledger, based on the UTXO IOTA coin value and the time it was created, which corresponds to the `Creation Slot` of the transaction that created the UTXO. @@ -402,7 +402,7 @@ else: - where its Potential Mana is calculated as `Potential Mana(Generation Amount, Output Creation Slot, Transaction Creation Slot)` according to [Potential Mana](#potential-mana) where: - - `Generation Amount` is defined as `Amount_i - Min Deposit`, if `Min Deposit > Amount_i`, otherwise `0`, where: + - `Generation Amount` is defined as `Amount_i - Min Deposit`, if `Min Deposit < Amount_i`, otherwise `0`, where: - `Amount_i` is the `Amount` of `i`, - `Min Deposit` is the minimum necessary storage deposit of `i`. - `Total Stored Mana` is the sum of Stored Mana for each input `i`: From b9cfc9f4352202b1a03d79ec755c0f2ac6a21c40 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 15 Jan 2024 09:47:47 +0000 Subject: [PATCH 150/157] Update variables in the potential mana section This change is mostly cosmetic; the result does not change with this update. --- tips/TIP-0039/tip-0039.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index dc4dc44cb..f7689b36d 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -317,11 +317,13 @@ applies the decay to the result, where: - `Mana Generated = Generate Mana(Amount, Slots Since Epoch Start)` - If `Output Creation Epoch < Transaction Creation Epoch - 1`: - Let `Epoch Index Diff` be `Transaction Creation Epoch - Output Creation Epoch`. - - Return `Potential Mana_0 - Potential Mana_n_1 + Potential Mana_n`, where - - `Potential Mana_n = Decay(Generate Mana(Amount, Slots Before Next Epoch), Epoch Index Diff)` - - `Potential Mana_n_1 = Decay(c, Epoch Index Diff - 1)` - - `Potential Mana_0 = c + Generate Mana(Amount, Slots Since Epoch Start) - (c >> Decay Factors Exponent)` + - Return `Potential Mana First Epoch + Potential Mana Intermediate Epochs + Potential Mana Last Epoch - Correction Term`, where + - `Potential Mana First Epoch = Decay(Generate Mana(Amount, Slots Before Next Epoch), Epoch Index Diff)` + - `Potential Mana Intermediate Epochs = c - c2` + - `Potential Mana Last Epoch = Generate Mana(Amount, Slots Since Epoch Start)` + - `Correction Term = c >> Decay Factors Exponent` - `c = Multiplication And Shift(Upper Bits(Amount, 32), Lower Bits(Amount, 32), Decay Factor Epochs Sum * Generation Rate , Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent)`. + - `c2 = Decay(c, Epoch Index Diff - 1)` ## Stored Mana From 207bf34cef8459b18d4a2d2b8e079d57f259dd48 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Tue, 16 Jan 2024 10:23:22 +0100 Subject: [PATCH 151/157] Format markdown --- tips/TIP-0039/tip-0039.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index f7689b36d..edd27d545 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -317,7 +317,9 @@ applies the decay to the result, where: - `Mana Generated = Generate Mana(Amount, Slots Since Epoch Start)` - If `Output Creation Epoch < Transaction Creation Epoch - 1`: - Let `Epoch Index Diff` be `Transaction Creation Epoch - Output Creation Epoch`. - - Return `Potential Mana First Epoch + Potential Mana Intermediate Epochs + Potential Mana Last Epoch - Correction Term`, where + - Return + `Potential Mana First Epoch + Potential Mana Intermediate Epochs + Potential Mana Last Epoch - Correction Term`, + where - `Potential Mana First Epoch = Decay(Generate Mana(Amount, Slots Before Next Epoch), Epoch Index Diff)` - `Potential Mana Intermediate Epochs = c - c2` - `Potential Mana Last Epoch = Generate Mana(Amount, Slots Since Epoch Start)` From 237e175b344d6dbf8d560f22679717d8a9bfb747 Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Tue, 16 Jan 2024 10:23:34 +0100 Subject: [PATCH 152/157] Add Mana Decay and Generation Test Vectors --- tips/TIP-0039/tip-0039.md | 77 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index edd27d545..473d6b514 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -444,6 +444,83 @@ to avoid differences in floating point operations on different machines. This lookup table is an integer approximation of 2Decay Factors ExponentDecay per Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. +# Test Vectors + +The protocol parameters used in the following test vectors are the same as in +[TIP-49](../TIP-0049/tip-0049.md#protocol-parameters-hash). + +## Mana Generation + +The following structure consists of a base token `amount` to which the [Potential Mana Generation](#potential-mana) +formula is applied with the given slots, resulting in the generated `potentialMana` value. + +```json +{ + "testVectors": [ + { + "amount": "1000000000", + "outputCreationSlot": 1, + "transactionCreationSlot": 10000, + "potentialMana": "76228441" + }, + { + "amount": "1000000000", + "outputCreationSlot": 9000, + "transactionCreationSlot": 10000, + "potentialMana": "7629394" + }, + { + "amount": "800000000000000000", + "outputCreationSlot": 1, + "transactionCreationSlot": 10000, + "potentialMana": "60982753715241244" + }, + { + "amount": "800000000000000000", + "outputCreationSlot": 9000, + "transactionCreationSlot": 10000, + "potentialMana": "6103515625000000" + } + ] +} +``` + +## Mana Decay + +The following structure consists of a `mana` value to which the [Decay function](#decay-function) is applied with +`epochIndexDiff = targetEpoch - creationEpoch`, resulting in the `decayedMana` value. + +```json +{ + "testVectors": [ + { + "mana": "25000000000", + "creationEpoch": 1, + "targetEpoch": 1000, + "decayedMana": "9907379812" + }, + { + "mana": "25000000000", + "creationEpoch": 900, + "targetEpoch": 1000, + "decayedMana": "22787760727" + }, + { + "mana": "9000000000000000", + "creationEpoch": 1, + "targetEpoch": 1000, + "decayedMana": "3566656732891364" + }, + { + "mana": "9000000000000000", + "creationEpoch": 900, + "targetEpoch": 1000, + "decayedMana": "8203593862010166" + } + ] +} +``` + # Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 9a64af2f3a91852f37e6a6a53267f4ff16e6c769 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 18 Mar 2024 11:11:22 +0000 Subject: [PATCH 153/157] remove lookup table --- tips/TIP-0039/tip-0039.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 473d6b514..1fb8792bd 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -185,8 +185,17 @@ point arithmetics (which do not expose the nodes to these rounding divergencies) require exact consensus over values. In particular, all the Mana and rewards calculations have to be done with fixed point arithmetics. -In the [lookup table](#lookup-table) section of this TIP, a lookup table is introduced that will be used in the rest of -this TIP, as a tool to perform calculations that would otherwise be done with floating point operations. +### Lookup Table + +The derivation of the `Mana Parameters::Decay Factors` protocol parameter, also referred to as the _lookup table_ is +described in the present section. This parameter must be calculated exactly once for a network's protocol parameters +to avoid differences in floating point operations on different machines. This Table is provided in the snapshot files; +thus, its definition is explained here just for the sake of clarification. The values on the table **must not** be calculated locally in the node or any application to avoid inconsistencies in the calculations. + +The lookup table is an integer approximation of 2Decay Factors ExponentDecay per +Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. +To obtain the decayed value of a certain amont of Mana `M` after `n` epochs has been passed, one should multiply +`M` by the entry of `Mana Parameters::Decay Factors` relative to `n` and then execute a right shift of `Decay Factors Exponent` bits. ### Decay Function @@ -435,15 +444,6 @@ A transaction is only valid if either of the following conditions holds: It is highly recommended to use overflow checks for arithmetic operations when calculating Mana balances to avoid over- and underflows. -## Lookup Table - -The derivation of the `Mana Parameters::Decay Factors` protocol parameter, also referred to as the _lookup table_ is -described in the following section. This parameter must be calculated exactly once for a network's protocol parameters -to avoid differences in floating point operations on different machines. - -This lookup table is an integer approximation of 2Decay Factors ExponentDecay per -Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. - # Test Vectors The protocol parameters used in the following test vectors are the same as in From 9fd519d0ff7b47c1299cc3898f65ed0aef8d290d Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Mon, 18 Mar 2024 12:16:31 +0000 Subject: [PATCH 154/157] minor updates in the decay function explanation --- tips/TIP-0039/tip-0039.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 1fb8792bd..24dc73f4e 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -194,8 +194,9 @@ thus, its definition is explained here just for the sake of clarification. The v The lookup table is an integer approximation of 2Decay Factors ExponentDecay per Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. -To obtain the decayed value of a certain amont of Mana `M` after `n` epochs has been passed, one should multiply +In general lines, to obtain the decayed value of a certain amont of Mana `M` after `n` epochs has been passed, the basic idea is to multiply `M` by the entry of `Mana Parameters::Decay Factors` relative to `n` and then execute a right shift of `Decay Factors Exponent` bits. +However, in some cases, a slighly more complex algorithm must be used, which we define in the next section. ### Decay Function From 98ab0ca3aa5ba9796f2de9e4f64e05878015772a Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Sun, 24 Mar 2024 16:45:34 +0000 Subject: [PATCH 155/157] minors updates in all the doc --- tips/TIP-0039/constraints.md | 26 +++++++ tips/TIP-0039/tip-0039.md | 137 ++++++++++++++++++----------------- 2 files changed, 95 insertions(+), 68 deletions(-) create mode 100644 tips/TIP-0039/constraints.md diff --git a/tips/TIP-0039/constraints.md b/tips/TIP-0039/constraints.md new file mode 100644 index 000000000..ddfe7b99a --- /dev/null +++ b/tips/TIP-0039/constraints.md @@ -0,0 +1,26 @@ + +# Parameters constraints + +Due to the use of fixed point arithmetics, some contraints on the Mana parameters are needed to prevent overflowing of the variables used for the Mana decay and generation calculations. + +In particular, the function `Multiplication And Shift(valueHi, valueLo, multFactor, shiftFactor)` is applied to the following variables: + +- `Multiplication And Shift(Upper Bits(value, 32), Lower Bits(value, 32), Decay Factors(m), Decay Factors Exponent)`. +- `Multiplication And Shift(Upper Bits(value, 32), Lower Bits(value, 32), slotIndexDiff * Generation Rate, Generation Rate Exponent)`. +- `Multiplication And Shift(Upper Bits(Amount, 32), Lower Bits(Amount, 32), Decay Factor Epochs Sum * Generation Rate , Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent)`. +By contruction, `Upper Bits(Amount, 32)` and `Upper Bits(Amount, 32)` will always use at most 32 bits (given that `Amount` uses at most 64 bits). + +Since `shiftFactor` must be an integer between 0 and 32, we have: + +- 0≤`Decay Factors Exponent`≤32. +- 0≤`Generation Rate Exponent`≤32. +- 0≤`Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent`≤32. + +The third variable `multFactor` must additionally use at most 32 bits, meaning that we have the following constraints: + +- `Decay Factors(m)`< 232 (which is equivalent, by contruction to 0≤`Decay Factors Exponent`≤3), +- `slotIndexDiff * Generation Rate`< 232, +- `Decay Factor Epochs Sum * Generation Rate`< 232, + + +TO DO: Rewards and maximum theoretical Mana in the system is smaller than 2Bits Count - 1 diff --git a/tips/TIP-0039/tip-0039.md b/tips/TIP-0039/tip-0039.md index 24dc73f4e..caa460fec 100644 --- a/tips/TIP-0039/tip-0039.md +++ b/tips/TIP-0039/tip-0039.md @@ -68,7 +68,7 @@ It is an essential element of the IOTA protocol, as it is used: - [**Block Issuance Credit**](#block-issuance-credit) (BIC) is the form of Mana used as an anti-spam mechanism to the block issuance process. During a transaction, Stored or Potential Mana can be _allotted as BIC_, which moves the Mana off the UTXO ledger and converts it to Block Issuance Credits. Only this form of Mana can be burnt to issue blocks. -- [**Mana Rewards**](#mana-rewards) reward participation in staking for validation and delegating IOTA coins. The Mana +- [**Mana Rewards**] reward participation in staking for validation and delegating IOTA coins. The Mana rewarded from these activities is not registered automatically in the UTXO ledger; thus, rewards must be claimed, as described in [TIP-40](../TIP-0040/tip-0040.md##mana-rewards). @@ -155,12 +155,6 @@ code. Defines fixed potential Mana generation per slot. - - Δ - - The duration of an epoch in years. - - Additionally, we use the protocol parameters, as defined in [TIP-49], and `Decay Factors Length`, defined as the length @@ -189,13 +183,15 @@ point arithmetics. The derivation of the `Mana Parameters::Decay Factors` protocol parameter, also referred to as the _lookup table_ is described in the present section. This parameter must be calculated exactly once for a network's protocol parameters -to avoid differences in floating point operations on different machines. This Table is provided in the snapshot files; -thus, its definition is explained here just for the sake of clarification. The values on the table **must not** be calculated locally in the node or any application to avoid inconsistencies in the calculations. +to avoid differences in floating point operations on different machines. This Table is provided in the snapshot files; +thus, its definition is explained here just for the sake of clarification. The values on the table **must not** be +calculated locally in the node or any application to avoid inconsistencies in the calculations. The lookup table is an integer approximation of 2Decay Factors ExponentDecay per -Epochn, for different values of `n` ranging from 1 to `Decay Factors Length`. -In general lines, to obtain the decayed value of a certain amont of Mana `M` after `n` epochs has been passed, the basic idea is to multiply -`M` by the entry of `Mana Parameters::Decay Factors` relative to `n` and then execute a right shift of `Decay Factors Exponent` bits. +Epochn
, for different values of `n` ranging from 1 to `Decay Factors Length`. +In general lines, to obtain the decayed value of a certain amont of Mana `M` after `n` epochs have been passed, the +basic idea is to multiply `M` by the entry of `Mana Parameters::Decay Factors` relative to `n` and then execute a +right shift of `Decay Factors Exponent` bits. However, in some cases, a slighly more complex algorithm must be used, which we define in the next section. ### Decay Function @@ -222,7 +218,7 @@ algorithm that will be defined below. First, we define three auxiliary functions `valueLo = Lower Bits(valueHi, shiftFactor) << (32 - shiftFactor) + (valueLo * multFactor) >> shiftFactor`. - Then compute `valueHi = (valueHi >> shiftFactor) + Upper Bits(valueLo, 32)`. - Then compute `valueLo = Lower Bits(valueLo, 32)`. - - Return `valueHi, valueLo`, representing the upper 32 and the lower 32 bits, respectively, of the result. + - Return `(valueHi<<32) + valueLo`, representing the result. With the functions above defined, we proceed to define the `Decay` function that takes as input a uint64 value `value` and decays it by the correct decay factor relative to `epochIndexDiff` epochs. OBS: note that here, @@ -232,16 +228,14 @@ necessarily corresponds to the `epochIndexDiff`th entry of the table. - Let `Decay(value, epochIndexDiff)` be: - If `value == 0` or `epochIndexDiff == 0`, return `value`. - Else: - - Let `valueHi = Upper Bits(value, 32)` and `valueLo = Lower Bits(value, 32)`. - Let `m` and `n` be natural numbers such that `m + n * Decay Factors Length = epochIndexDiff`, and `m < Decay Factors Length`. - Apply - `valueHi, valueLo = Multiplication And Shift(valueHi, valueLo, Decay Factors(Decay Factors Length), Decay Factors Exponent)` + `value = Multiplication And Shift(Upper Bits(value, 32), Lower Bits(value, 32), Decay Factors(Decay Factors Length), Decay Factors Exponent)` `n` times. - - Apply `valueHi, valueLo = Multiplication And Shift(valueHi, valueLo, Decay Factors(m), Decay Factors Exponent)` + - Apply `value = Multiplication And Shift(Upper Bits(value, 32), Lower Bits(value, 32), Decay Factors(m), Decay Factors Exponent)` once. - - The function should return `valueHi, valueLo` combined into a single `uint64`, i.e., it returns - `valueHi << 32 + valueLo`. + - Return `value`. Other implementations of the functions above are possible; however, one must be careful with the order of operations, which must be done as defined above. Having a well-defined order is crucial since sequences of divisions and @@ -259,7 +253,7 @@ transaction that created the UTXO. We model the potential Mana generated by an output holding `S` IOTA coins as the combination of a fixed generation per slot `γS` and a decay equivalent to a multiplication by Decay per Epoch every time an epoch ends. -![](./img/slots_potential_mana-2.png) +![Creation and consumption slots of an output](./img/slots_potential_mana-2.png) Let `i` be the epoch of the creation slot and `j` be the epoch of the consumption slot. Let `n=j-i`, and for the sake of the explanation, assume `n`>1. All the Mana generated in epoch `i` "crosses" n decay boundaries; thus, it must be @@ -298,8 +292,10 @@ of decay (note that we use some of the procedures and constants defined in the l - `Generate Mana(value,slotIndexDiff)` returns the generated mana from holding `value` tokens for `slotIndexDiff` slots, without applying any decay: - if `slotIndexDiff` == 0 or `Generation Rate` == 0, the procedure returns `0` - - otherwise, it returns `Multiplication And Shift(value, slotIndexDiff * Generation Rate, Generation Rate Exponent)`. + - otherwise, it returns `Multiplication And Shift(Upper Bits(value, 32), Lower Bits(value, 32), slotIndexDiff * Generation Rate, Generation Rate Exponent)`. +This means that `slotIndexDiff * Generation Rate` must be an integer smaller than 2 `32` and +`Generation Rate Exponent` must be an integer between 0 and 32. Now we define the procedure `Potential Mana` that actually calculates the Potential Mana using the formulas defined in the last section (including the decays): @@ -370,74 +366,79 @@ on Mana burned from the block issuance credits by the block. It is important to network. It does not care about the transactions inside the blocks. The example below shows a ledger with a conflicting branch (perhaps due to a double spend), so only one branch (either -the set of red or the set of green transactions) can ultimately modify the ledger, not both. However, all these blocks +the set of red or the set of green transactions) can ultimately modify the ledger, but never both. However, all these blocks must be gossiped, whether they contain red or green transactions. Thus, they must pay for the BIC used to get through schedulers regardless of whether the transaction within modifies the ledger. This is why BIC cannot be burned by a transaction - it can only be burned by a block. -![](./img/data_flow_overview.png) +![Data flow overview](./img/data_flow_overview.png) -Because a block cannot modify the UTXO ledger but the Mana the block burns must be deducted from the account's BIC -balance, the BIC is stored in an accounts ledger. This ledger is a map from an Account ID to block issuer data, which -includes the BIC balance, the block issuer keys and when the Block Issuer Feature expires among other data. This -separate ledger is partly derived from the Block Issuer Feature in an account in the UTXO ledger. The BIC balance of an -account can only be modified in two ways: +Because a block cannot modify the UTXO ledger but only the Mana balances, the amount burnt by a block must be deducted +from the account's BIC balance. The BIC is stored in an accounts ledger; +i.e., a map from the Account IDs to the block issuers' data, +including the BIC balance, the block issuer keys and the Block Issuer Feature expiration (among other data). +The BIC balance of an account can only be modified in two ways: -- BIC is subtracted from the ledger when the corresponding account issues a block signed by one of its Block Issuer - Keys. +- BIC is subtracted from the ledger when the corresponding account issues a block signed by one of its Block Issuer Keys. - BIC is increased in the ledger when a transaction allots Mana to that account. -Updates to the BIC balance happen upon slot commitments. Mana Decay is applied to the BIC for the accounts whose BIC was +Updates to the BIC balance happen upon slot commitments. Mana Decay is applied to the BIC of the accounts whose BIC was changed in that slot. ### Block Issuance Credit Semantic Validation -- When applying Mana Decay to BIC at the end of a slot, it must be applied as follows: - - Let `BIC_i` be the amount of BIC held by the account at the end of slot `i`. Since all additions of allotted BIC - were already decayed in that slot, only the previous value of BIC must be decayed, relative to the last slot it was - decayed in, by applying: +When applying Mana Decay to BIC at the end of a slot, it must be applied as follows: -TODO: This function doesn't take into account the last time the BIC was decayed and the current time. +- Let `i` be a slot where the BIC of an account `account` was changed. +Let `BIC(i)` be the amount of BIC held by `account` at the end of slot `i`. +- Suppose that slot `i+d` is the first slot after `i` that the BIC of `account` is changed. +- Suppose in this slot, the account issued a block (thus, burning `burnt BIC` BIC) containing a transaction that allots +`allotted BIC` BIC to the same account. +- Let `epoch(i)` and `epoch(i+d)` be the epochs to which slots `i` and `i+d` belong, respectively. +- Since `allotted BIC` was already decayed (otherwise, the transaction allotting this BIC would fail its +[transaction validation rules](#mana-transaction-validation-rules)), only the previous value of BIC must be decayed, +relative to the last slot it was decayed in, by applying: + - `decayed old BIC = Decay(BIC(i), epoch(d+i)-epoch(i))` +- Then, the balance is updated with the burnt and allotted amounts: + - `BIC(i+d) = decayed old BIC + allotted BIC - burnt BIC` -```go -if BIC > 0: - new_BIC = Decay(BIC, 1) -else: - new_BIC = BIC -``` +TO DO: talk to Andrew about where exactly the BIC balance is checked. ## Mana Transaction Validation Rules -- Let `Total Mana In` be the total amount of Mana on the input side of a transaction, consisting of +A transaction can only be valid if either of the following conditions holds (note that these are not the _only_ +conditions for a transaction to be valid, but the ones relative to Mana balances): + +- `Total Mana In == Total Mana Out`. +- `Total Mana In > Total Mana Out` and the _Can Burn Mana_ Flag in the _Transaction Capabilities_ is **set**. + +where `Total Mana In` and `Total Mana Out` are defined as follows: + +- Let `Transaction Creation Slot` be the `Creation Slot` of the transaction being validated. For each input `i` +of the transaction, we define: + - `Input Creation Slot(i)` is the `Creation Slot` of the transaction that created each input `i`. + - `Amount(i)` is the `Amount` of input `i` . + - `Min Deposit(i)` is the minimum necessary storage deposit of `i`. + - `Stored Mana_i` is the `Mana` of `i`. + - `Generation Amount(i)` is defined as `Amount(i) - Min Deposit(i)`, if `Min Deposit(i) < Amount(i)`, and `0` otherwise. + +- Then, `Total Mana Out` will be the total amount of Mana on the output side of a transaction, consisting of + `Total Stored Mana + Total Allotted Mana`, where: + - `Total Stored Mana` is the sum of `Mana` fields for each output. + - `Total Allotted Mana` is the sum of `Mana` fields for each _Allotment_. +- Additionally, `Total Mana In` will be the total amount of Mana relative to the input side of a transaction, consisting of `Total Potential Mana + Total Stored Mana + Total Mana Rewards`, where: - - `Transaction Creation Slot` is the `Creation Slot` of the transaction, - - `Output Creation Slot` is the `Creation Slot` of the transaction that created the output. - - `Total Potential Mana` is the sum of Potential Mana for each input `i`: - - where its Potential Mana is calculated as - `Potential Mana(Generation Amount, Output Creation Slot, Transaction Creation Slot)` according to - [Potential Mana](#potential-mana) where: - - `Generation Amount` is defined as `Amount_i - Min Deposit`, if `Min Deposit < Amount_i`, otherwise `0`, where: - - `Amount_i` is the `Amount` of `i`, - - `Min Deposit` is the minimum necessary storage deposit of `i`. - - `Total Stored Mana` is the sum of Stored Mana for each input `i`: - - where its Stored Mana is calculated as - `Stored Mana(Stored Mana_i, Output Creation Slot, Transaction Creation Slot)`, where: - - `Stored Mana_i` is the `Mana` of `i`. - - `Total Mana Rewards` is the sum of total claimable rewards from each input referenced by a _Reward Input_ in the - transaction, each of which is calculated as follows: + - `Total Potential Mana` is the sum of the generated Potential Mana for each input `i`. + Each of those Potential Mana factors are calculated as + `Potential Mana(Generation Amount(i), Input Creation Slot(i), Transaction Creation Slot)` according to [Potential Mana](#potential-mana). + - `Total Stored Mana` is the sum of Stored Mana for each input `i`. + Each of those Stored Mana factors are calculated as `Stored Mana(Stored Mana(i), Input Creation Slot(i), Transaction Creation Slot)`. + - `Total Mana Rewards` is the sum of total claimable rewards from each input referenced by a _Reward Input_ in the transaction, + each of which is calculated as follows: - If the pointee of the _Reward Input_ is an _Account Output_ with its `Account ID`, the rewards are calculated with [`Validator Rewards(Account ID)`](../TIP-0040/tip-0040.md#validator-rewards). - If the pointee of the _Reward Input_ is a _Delegation Output_ with its `Delegation ID`, the rewards are calculated with [`Delegation Rewards(Delegation ID)`](../TIP-0040/tip-0040.md#delegator-rewards). -- Let `Total Mana Out` be the total amount of Mana on the output side of a transaction, consisting of - `Total Stored Mana + Total Allotted Mana`, where: - - `Total Stored Mana` is the sum of `Mana` fields for each output. - - `Total Allotted Mana` is the sum of `Mana` fields for each _Allotment_. - -A transaction is only valid if either of the following conditions holds: - -- `Total Mana In == Total Mana Out`. -- `Total Mana In > Total Mana Out` and the _Can Burn Mana_ Flag in the _Transaction Capabilities_ is **set**. | :warning: Potential Overflows | | ----------------------------- | @@ -450,7 +451,7 @@ and underflows. The protocol parameters used in the following test vectors are the same as in [TIP-49](../TIP-0049/tip-0049.md#protocol-parameters-hash). -## Mana Generation +## Vectors for Mana Generation The following structure consists of a base token `amount` to which the [Potential Mana Generation](#potential-mana) formula is applied with the given slots, resulting in the generated `potentialMana` value. @@ -486,7 +487,7 @@ formula is applied with the given slots, resulting in the generated `potentialMa } ``` -## Mana Decay +## Vectors for Mana Decay The following structure consists of a `mana` value to which the [Decay function](#decay-function) is applied with `epochIndexDiff = targetEpoch - creationEpoch`, resulting in the `decayedMana` value. From 1b24bd78dffe1c8b0723150d0dcc9bae0d7cf81c Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Thu, 28 Mar 2024 09:27:37 +0000 Subject: [PATCH 156/157] Update constraints.md minor addition --- tips/TIP-0039/constraints.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tips/TIP-0039/constraints.md b/tips/TIP-0039/constraints.md index ddfe7b99a..5ade2ae07 100644 --- a/tips/TIP-0039/constraints.md +++ b/tips/TIP-0039/constraints.md @@ -15,6 +15,7 @@ Since `shiftFactor` must be an integer between 0 and 32, we have: - 0≤`Decay Factors Exponent`≤32. - 0≤`Generation Rate Exponent`≤32. - 0≤`Decay Factor Epochs Sum Exponent+generationRateExponent-slotsPerEpochExponent`≤32. +- 0≤`generationRateExponent-slotsPerEpochExponent`≤32. The third variable `multFactor` must additionally use at most 32 bits, meaning that we have the following constraints: From 9c3760915d60505bf3d46ee108fb3e83a31648ad Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Thu, 28 Mar 2024 14:26:39 +0000 Subject: [PATCH 157/157] Update constraints.md --- tips/TIP-0039/constraints.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tips/TIP-0039/constraints.md b/tips/TIP-0039/constraints.md index 5ade2ae07..b38efa550 100644 --- a/tips/TIP-0039/constraints.md +++ b/tips/TIP-0039/constraints.md @@ -21,7 +21,4 @@ The third variable `multFactor` must additionally use at most 32 bits, meaning t - `Decay Factors(m)`< 232 (which is equivalent, by contruction to 0≤`Decay Factors Exponent`≤3), - `slotIndexDiff * Generation Rate`< 232, -- `Decay Factor Epochs Sum * Generation Rate`< 232, - - -TO DO: Rewards and maximum theoretical Mana in the system is smaller than 2Bits Count - 1 +- `Decay Factor Epochs Sum * Generation Rate`< 232.