From 2e32ec82f5a9234886df7302c766c86122c5f256 Mon Sep 17 00:00:00 2001 From: oliviasaa Date: Thu, 28 Mar 2024 15:14:20 +0000 Subject: [PATCH] add parameter contraints --- tips/TIP-0040/constraints.md | 187 +++++++++++++++++++++++++++++ tips/TIP-0040/tip-0040.md | 222 +++++++++++++++++------------------ 2 files changed, 296 insertions(+), 113 deletions(-) create mode 100644 tips/TIP-0040/constraints.md diff --git a/tips/TIP-0040/constraints.md b/tips/TIP-0040/constraints.md new file mode 100644 index 000000000..bb50c7369 --- /dev/null +++ b/tips/TIP-0040/constraints.md @@ -0,0 +1,187 @@ +# Parameters constraints + +Due to the use of fixed point arithmetics, some contraints on the rewards parameters are needed to prevent overflowing of the variables used for the calculations. + +## Constraints on the Mana Supply + +The first and most straighforward contraint is that the total maximum theoretical Mana in the system should not use more than $\text{Bits Count}$ bits. + +Let's start by calculating the Mana in the system generated by holding tokens $\text{Mana Holders}(n)$ until epoch $n$. + +$$ + \text{Mana Holders}(n)=\frac{\text{Token Supply}*\text{Generation Rate}}{1-\text{Decay per Epoch}}* 2^{\text{Slots per Epoch Exp}-\text{Generation Rate Exp}} (1-\text{Decay per Epoch}^{n+1}) +$$ +with $\text{Decay per Epoch}=\text{Decay per Year}^{\frac{\text{Seconds per Epoch}}{\text{Seconds per Year}}}$. + +The maximum Mana in the system generated by holding tokens $\text{Max Mana Holders}$ is equivalent to the potential Mana generated by an output holding $\text{Token Supply}$ IOTA coins until epoch $n$, for $n$ large enough. This results: + +$$ +\begin{align*} +\text{Max Mana Holders} = \frac{\text{Token Supply}*\text{Generation Rate}}{1-\text{Decay per Epoch}}2^{\text{Slots per Epoch Exp}-\text{Generation Rate Exp}} +\end{align*} +$$ + +We denote by $\text{Max Reward Rate}(n) = \text{Max to Target Ratio} * \text{Target Rewards Rate}(n)$ the theoretical maximum reward distributed at epoch $n$. +In the case of fixed or top stakers based committees, the actual reward distributed per epoch is at most $\text{Target Rewards Rate}(n)$, i.e., $\text{Max to Target Ratio} = 1$. +For random committees, see [Random committees](#random-committees). + +### Mana Supply in the bootstrapping Phase + +In the bootstrapping Phase, the target reward decreases each epoch until reaching $\text{Final Target Rewards Rate}$. +The maximum amount of Mana distributed as rewards until epoch $n$ is: + +$$ +\sum_{i=1}^{n} \text{Decay}(\text{Max Reward Rate}(i),n-i) +$$ + +Since $\text{Max Reward Rate}(i)$ is proportional to the epoch target reward, this is equivalent to + +$$ +\begin{align*} +&\sum_{i=1}^{n} \text{Decay}(\text{Decay}(\text{Max Reward Rate}(1),i-1),n-i)\\ +=&n \text{Decay}(\text{Max Reward Rate}(1),n-1)\\ +=&n \text{Decay per Epoch}^{n-1} \text{Max Reward Rate}(1) +\end{align*} +$$ + + + +the function above is increasing if $n\leq \frac{-1}{\log(\text{Decay per Epoch})}$ and decreasing otherwise (i.e., it is a concave function). However, since the $\text{Bootstrapping Duration}$ is set such that $\text{Bootstrapping Duration in Years}*\text{Beta per Year}=1$, we have that $\text{Bootstrapping Duration in Years} = \frac{1}{\text{Beta per Year}}=\frac{-1}{\log(\text{Decay per Year})}$. Then, the maximum amount of Mana distributed as rewards in the bootstrapping Phase is achieved at $\text{Bootstrapping Duration}$, i.e., the maximum is + +$$ +\begin{align*} +&\text{Max Mana Supply Bootstrapping}\\ +&=\frac{1}{-\log(\text{Decay per Epoch})}* \text{Max to Target Ratio}*\text{Final Target Rewards Rate} +\end{align*} +$$ + +By definition, we have that $\text{Final Target Rewards Rate}$ is + +$$ +\begin{align*} +&\text{Final Target Rewards Rate}=\text{Token Supply}*\text{Reward To Generation Ratio}\\ +*&\text{Generation Rate}*2^{\text{Slots per Epoch Exp}-\text{Generation Rate Exp}} +\end{align*} +$$ + +Then, the Maximum Mana supply in the bootstrapping phase is + + + +$$ +\begin{align*} +&\text{Max Mana Supply Bootstrapping}\\ +&=\text{Token Supply}*\text{Generation Rate}*2^{\text{Slots per Epoch Exp}-\text{Generation Rate Exp}}\\ +&\left(\text{Reward To Generation Ratio}*\frac{1}{-\log(\text{Decay per Epoch})}* \text{Max to Target Ratio}\right.\\ ++&\left.\frac{1}{1-\text{Decay per Epoch}}\right)\\ +&\leq \text{Token Supply}*\text{Generation Rate}*2^{\text{Slots per Epoch Exp}-\text{Generation Rate Exp}}\\ +&\frac{1+\text{Reward To Generation Ratio}*\text{Max to Target Ratio}}{1-\text{Decay per Epoch}} +\end{align*} +$$ + +### Mana Supply after the bootstrapping Phase + +By construction, $\text{Final Target Rewards Rate}$ is such that the target reward per epoch is $\text{Reward To Generation Ratio}$ times the generation by holding tokens in that epoch. + +Then, we have that the total Mana in the system will never be larger than $\text{Max Mana Holders} (1 + \text{Max to Target Ratio} * \text{Reward To Generation Ratio})$, i.e. the Mana circulating Supply will be always smaller than : + +$$ +\begin{align*} +&\text{Max Mana Supply}\\ +&=\text{Token Supply}*\text{Generation Rate}*2^{\text{Slots per Epoch Exp}-\text{Generation Rate Exp}}\\ +&\frac{1+\text{Reward To Generation Ratio}*\text{Max to Target Ratio}}{1-\text{Decay per Epoch}} +\end{align*} +$$ + +which is the same bound found for the bootstrapping Phase. +Thus, the protocol parameters should be set so that the $\text{Max Mana Supply}$ above is at most $2^{\text{Bits Count}}-1$. + +### Mana Supply for Random committees + +In the case of random commitees, we cap the individual pool reward such that no pool will receive more than $\text{Max Pool Reward}(n) = \text{Max Reward Coeff} * \text{Target Rewards Rate}(n)$ per epoch. +Then, in a single epoch, no more than $\text{Target Committee Size} * \text{Max Reward Coeff} * \text{Target Rewards Rate}(n)$ Mana will be distributed, i.e., in this case, $\text{Max to Target Ratio} = \text{Target Committee Size} * \text{Max Reward Coeff}$. +Since, in general, $\text{Target Committee Size} * \text{Max Reward Coeff}$ might be larger than 1, we must alredy set proper maximim values for $\text{Max to Target Ratio}$ to prevent overflowing in case of a future change in the committee selection. +Here, we set $\text{Max to Target Ratio}=20$. +Note that, for fixed committees, this ratio is naturally respected, without the need to add any type of cap in the rewards. +However, in the case of a future protocol upgrade such that the committee selection becomes random, a cap respecting a maximum of $\text{Max to Target Ratio}=20$ must be introduced. + +## Constraints due to fixed point arithmetics + +Additionally to the parameter constraints to prevent the Mana supply from overflowing, other parameter constraints must be introduced to that the function defined in TIP 40 do not overflow using 64 bits variables. + +In particular, in this TIP we define the following operations: +- `Token Supply << Profit Margin Exponent`: this value must be smaller than 264, +- `Pool Coefficient = ((Pool Stake(i) << Pool Coefficient Exponent)/Total Stake) + (Validator Stake(i) << Pool Coefficient Exponent) / Total Validator Stake`: +Since both `Pool Stake(i)` and `Validator Stake(i)` are at most `Token Supply`, to not overflow the calculation, `Pool Coefficient Exponent` must be such that (Token Supply << Pool Coefficient Exponent)< 264. +`Pool Coefficient` will then use at most `Pool Coefficient Exponent + 1` bits. +- `res = (Pool Coefficient * Target Rewards Rate(n))>>PoolCoefficientExponent`: this implies that `Pool Coefficient * Target Rewards Rate(n))` must always be smaller than 264, which is guaranteed by the condition Initial Target Rewards Rate <263-Pool Coefficient Exponent. +- `Pool Reward = ((res * Epoch Performance Factor)/Validation Blocks Per Slot)>>1`: since `res` is at most two times `Initial Target Rewards Rate`, and `Epoch Performance Factor` is at most `Validation Blocks Per Slot <= 32`, this imples that Initial Target Rewards Rate * Validation Blocks Per Slot < 263. + +- `Profit Margin Factor = (Profit Margin(n) * (Pool Rewards(n) - Fixed Cost(n))) >> Profit Margin Exponent`: this implies that `Initial Target Rewards Rate<2^(64-Profit Margin Exponent) ` + +## Constraints due to parameter compatibility + +To avoid locally calculating the parameters, some of them are provided in the snapshot file, even thought they not are defined independently in the Whitepaper. +To avoid problems in the parameter setting, we define some sanity checks for these parameters below: + +## Lookup Table and Annual Decay + +Let `Seconds In An Epoch = Slot Duration In Seconds << Slots Per Epoch Exponent` and `Seconds In A Year = 60 * 60 * 24* 365`. +Then the epoch duration in years is given by `Epoch Duration In Years = Seconds In An Epoch/Seconds In A Year`. +Additionally, let `Annual Decay Factor = Annual Decay Factor Percentage/100`. + +The entry `Lookup Table(epochDiff)` in the Lookup table relative to `epochDiff` should be such that + +`0 <= delta < 1`, where + +`delta = (Annual Decay Factor)^(epochDiff*Epoch Duration In Years)*(2**decay Factor Exp) - Lookup Table(epochDiff)` + +## Initial and Final rewards + +Let `Seconds In An Epoch = Slot Duration In Seconds << Slots Per Epoch Exponent` and `Seconds In A Year = 60 * 60 * 24* 365`. +Then the epoch duration in years is given by `Epoch Duration In Years = Seconds In An Epoch/Seconds In A Year`. +The bootstrapping duration in years is, then: +`Bootstrapping Duration In Years = Epoch Duration In Years * Bootstrapping Duration` +Additionally, let `Annual Decay Factor = Annual Decay Factor Percentage/100`. + +Let `Expected Final Target Rewards Rate = (Total Supply * Reward To Generation Ratio * Generation Rate) >> (Generation Rate Exponent - Slots Per Epoch Exponent)` and `Expected Initial Target Rewards Rate = Final Target Rewards Rate / (Annual Decay Factor ^ Bootstrapping Duration In Years)`. + +Then, we need + +`0 <= Expected Final Target Rewards Rate - Final Target Rewards Rate < 1` +and +`0 <= Expected Initial Target Rewards Rate - Initial Target Rewards Rate < 1` + +## Bootstrapping Duration and Decay + +Let `Seconds In An Epoch = Slot Duration In Seconds << Slots Per Epoch Exponent` and `Seconds In A Year = 60 * 60 * 24 * 365`. +Then the number of epochs in a years is given by `Epochs In An Year = Seconds In A Year/Seconds In An Epoch`. +Additionally, let `Annual Decay Factor = Annual Decay Factor Percentage/100`. +Translating this to an exponential decay (as in the Whitepaper), we have that `Beta Per Year = -log(Annual Decay Factor)`. + +The bootstrapping duration should be an integer approximation of `Epochs In An Year/Beta Per Year` + +## Decay Factor Epoch Sum and Decay + +Decay Factor Epoch Sum should be an integer approximation of + +`2^Decay Factor Epoch Sum Exponent* Decay per Epoch/(1-Decay per Epoch)` diff --git a/tips/TIP-0040/tip-0040.md b/tips/TIP-0040/tip-0040.md index 0c8862edb..372440846 100644 --- a/tips/TIP-0040/tip-0040.md +++ b/tips/TIP-0040/tip-0040.md @@ -143,7 +143,7 @@ follows: ## Committee Selection -![](./assets/selection-timing.png) +![Overview of the timing around committee selection in epochs](./assets/selection-timing.png) _This figure gives an overview of the timing around committee selection in epochs. Note that the exact length of those windows is not accurately depicted here and instead depends on the value of the corresponding Protocol Parameters._ @@ -188,7 +188,7 @@ taken: The selected members of the committee are expected to issue _Validation Blocks_, defined in [TIP-46](../TIP-0046/tip-0046.md). Only the votes of those selected into the committee are considered to determine the Witness Weight, used for the acceptance of blocks, and Approval Weight, used for conflict resolution and transaction -acceptance. The [performance](#performance-factor) of a validator is determined by the issued Validation Blocks, and +acceptance. The [performance](#epoch-performance-factor) of a validator is determined by the issued Validation Blocks, and affects the validator pool's Mana rewards. # Delegation @@ -413,15 +413,18 @@ defined in [TIP-49](../TIP-0049/tip-0049.md). # Mana Rewards -Mana Rewards are claimed and tracked for past epochs on an epoch level. For an ongoing epoch, they are tracked on a slot -level and are then combined into an epoch rewards entry when the epoch ends. Rewards for an epoch become claimable when -the epoch ends, that is, when its last slot is committed. +Mana Rewards are claimed and tracked for past epochs on an epoch level. +For an ongoing epoch, they are tracked on a slot level and are then combined into an epoch rewards entry when the +epoch ends (i.e., when its last slot is committed). +Rewards for an epoch become claimable only after the epoch ends. +In the following sections, we define how the rewards are calculated and tracked at the slot level (i.e., for a +still unfinished epoch) and how they are combined and tracked at the epoch level (i.e., after the epoch ends). -## Slot Level +## Calculations done at the Slot Level -For each slot, the performance factor of each validator in the selected committee must be tracked. For an epoch, this -results in a list of performance factors for a validator. The rewards for an ongoing epoch are tracked by keeping a map -of slot indices to a map of the validator's activity in that slot, identified by the `Validator ID`. The activity is +For each slot, the performance factor of each validator in the selected committee must be tracked. For an ongoing epoch, +this results in a list of performance factors for a validator. The rewards for an ongoing epoch are tracked by keeping a +map of slot indices to a map of the validator's activity in that slot, identified by the `Validator ID`. The activity is thus tracked per slot, per validator with objects consisting of these data: @@ -433,7 +436,7 @@ thus tracked per slot, per validator with objects consisting of these data: - + @@ -458,53 +461,58 @@ This performance factor for a slot is defined as follows. `Subslot Duration = Slot Duration In Seconds/Validation Blocks Per Slot` given by `[Slot Start + (i - 1) * Subslot Duration, Slot Start + i * Subslot Duration)`, for `i = 1,...,Validation Blocks Per Slot`. -- Determine how many of these subslots have at least one validation block issued in them and set the bit with the - subslot index in the `Slot Activity Vector`. This is the `Slot Performance Factor`. -- Count the number of validation blocks issued in this slot as `Blocks Issued Count`. This value should be capped at - `Validation Blocks Per Slot`. If the number of blocks issued in this slot is greater than - `Validation Blocks Per Slot`, set `Blocks Issued Count` to `Validation Blocks Per Slot + 1` to signal that the - validator issued more validation blocks than it was supposed to and that it should be punished when combining the slot - performance factors into an epoch performance factor. - - Since `Validation Blocks Per Slot` must be less or equal than 32, this approach will not overflow - `Blocks Issued Count`. - -## Epoch Level +- Determine which of these subslots have at least one validation block issued in them. + Set `Slot Activity Vector` such that: + - If subslot `i` has at least one validation block issued in it, set the bit in `Slot Activity Vector` with the index `i` to 1. + - Otherwise, set the bit in `Slot Activity Vector` with the index `i` to 0. +- Set `Blocks Issued Count` to the total number of validation blocks issued in this slot. + Validators are supposed to issue at most `Validation Blocks Per Slot` validation blocks per slot. + If the number of blocks issued in this slot is greater than `Validation Blocks Per Slot`, + set `Blocks Issued Count` to `Validation Blocks Per Slot + 1` to signal that the + validator issued more validation blocks than it was supposed to and that it should be punished + when combining the slot performance factors into an epoch performance factor. + Since `Validation Blocks Per Slot` must be less or equal than 32, this approach will not overflow `Blocks Issued Count`. +- The `Slot Performance Factor` is then defined as + - The sum of the bits in `Slot Activity Vector`, if `Blocks Issued Count ≤ Validation Blocks Per Slot`. + - 0, otherwise. + +The `Slot Performance Factor` is then an integer between 0 and `Validation Blocks Per Slot`. +Note that there is no need to explicitly calculate the `Slot Performance Factor` for each slot, since they will all be aggregated +as an single `Epoch Performance Factor` after the epoch ends. +Instead, one should simply store all `Slot Activity Vector` and `Blocks Issued Count` (one pair for each slot) until the epoch ends. + +## Mana Rewards at a Epoch Level + +After an epoch has ended, the performance factors tracked at the slot level can be combined into a single performance factor for the whole epoch. +The profit margin of the epoch (which is common for all pools) is also calculated. +With those values determined, the rewards for the whole pool are calculated. +We define the procedure to do so in the next sections. ### Epoch Performance Factor -#### Input values - -- Let `Slot Performance Factor Array` be the array of _Slot Performance Factors_ of a given validator in each slot of an - epoch. - -#### Calculations +The `Epoch Performance Factor` is given by the average between the values of `Slot Performance Factor`, rounded down to the nearest integer. +This can be calculated as the sum of bits set to `1` in each `Slot Activity Vector` with a subsequent _zero-fill right-shift_ operation by +`Slots Per Epoch Exponent`. If the validator issued more than `Validation Blocks Per Slot` validation blocks in any slot, that is, if +`Blocks Issued Count > Validation Blocks Per Slot` in any of the slots in the epoch, then `Epoch Performance Factor` is set to 0 as a form of +punishment. +Note that the value of the `Epoch Performance Factor` will be an integer between 0 and `Validation Blocks Per Slot`. -- Then `Epoch Performance Factor` is given by the average between these values, rounded down to the nearest integer. - This can be calculated as the sum of bits set to `1` in each `Slot Activity Vector` with a subsequent _zero-fill - right-shift_ operation by `Slots Per Epoch Exponent`. -- If the validator issued more than `Validation Blocks Per Slot` validation blocks in any slot, that is, if - `Blocks Issued Count > Validation Blocks Per Slot`, then `Epoch Performance Factor` is set to 0 as a form of - punishment. - - Note that the value of the `Epoch Performance Factor` will be an integer between 0 and `Validation Blocks Per Slot`. +### Profit Margin -### Profit Margins - -#### Input values +#### Input values for the Profit Margin calculation - Let `Total Stake` be the sum of all `Pool Stake` values, that is, the total amount of delegated and staked IOTA coins in the selected committee. - Let `Total Validator Stake` be the sum of `Validator Stake(i)` for each validator `i` in the selected committee. -#### Parameters - -- Let `Profit Margin Exponent` be 8. - -#### Calculations +#### Profit Margin calculation +- Let `Profit Margin Exponent` be as definced in [TIP-49](../TIP-0049/tip-0049.md). - Given the values defined above, then `Profit Margin = (Total Validator Stake << Profit Margin Exponent)/(Total Validator Stake + Total Stake)`. Note that this will be an integer strictly smaller than 2Profit Margin Exponent, so `Profit Margin` can be set to use `Profit Margin Exponent` bits. +- To prevent overflows in the calculation above, (Token Supply << Profit Margin Exponent)< 264, where `Token Supply` is the current token supply on the network, as defined in [TIP-49](../TIP-0049/tip-0049.md). The `Profit Margin` must be tracked for each epoch: @@ -523,9 +531,9 @@ The `Profit Margin` must be tracked for each epoch:
Slot Activity Vector uint32A bitmap where each bit corresponds to a subslot in the slot for which the performance factor is tracked. Hence, the number of subslots (equal to Validation Blocks Per Slot) cannot be greater than 32.A bitmap where each bit corresponds to a subslot in the slot for which the performance factor is tracked.
Blocks Issued Count
-### Epoch Rewards +### Pool Rewards for an Epoch -The rewards of an epoch are tracked by keeping a map from epoch indices to a map from `Validator ID`s to values +The pool rewards of an epoch are tracked by keeping a map from epoch indices to a map from `Validator ID`s to values consisting of these fields: @@ -551,52 +559,36 @@ consisting of these fields:
-The next section defines how these values can be obtained from the slot-level data, after the commitment of the last +The present section defines how `Pool Rewards` can be obtained from the slot-level data, after the commitment of the last slot of that epoch. -### Slot-Epoch Conversion of the Rewards - -The following section specifies how to convert the slot-level data into epoch-level data. - -#### Parameters needed for calculations: - -- `Bootstrapping Duration` = 1154 epochs (approximately 3 years) -- `Reward To Generation Ratio` = 2 (the ratio of final target rewards rate to Mana generation rate) -- `Final Target Rewards Rate = (Total Supply * Reward To Generation Ratio * Generation Rate) >> (Generation Rate Exponent - Slots Per Epoch Exponent)`. - - This is the constant reward per epoch after the bootstrapping phase. -- `Initial Target Rewards Rate = Final Target Rewards Rate / ((Annual Decay Factor Percentage / 100) ^ Bootstrapping Duration In Years)`. -- `Pool Coefficient Exponent = 11`. - -#### Input values +#### Input values for Pool Rewards calculations +- Let `Bootstrapping Duration`, `Reward To Generation Ratio`, `Final Target Rewards Rate`, `Initial Target Rewards Rate`, and `Pool Coefficient Exponent` be as defined in [TIP-49](../TIP-0049/tip-0049.md). - Let `Validator Stake(i)` be the amount of IOTA coins staked by the validator with Account ID `i`, i.e. the `Staked Amount` in the _Staking Feature_ of the validator at the end of the registration slot. - Let `Pool Stake(i)` be the total amount of delegated and staked IOTA coins by the validator pool `i`, identified by - the validator's `Account ID`, which was determined at the time of the pool stake calculation, i.e. the end of the - registration slot. -- Let `Total Stake` be the sum of all `Pool Stake(i)` where validator `i` is in the selected committee. -- Let `Total Validator Stake` be the sum of `Validator Stake(i)` for each validator `i` in the selected committee. +the validator's `Account ID`, which was determined at the time of the pool stake calculation, i.e. the end of the +registration slot. +- Let `Total Stake` be the sum of `Pool Stake(i)` for all validators `i` in the selected committee. +- Let `Total Validator Stake` be the sum of `Validator Stake(i)` for all validators `i` in the selected committee. -#### Calculations +#### Pool Rewards calculations - The total target rewards rate `Target Rewards Rate(n)` for an epoch index `n` is defined as: - - `Initial Target Rewards Rate * Decay(n)` if `n <= Bootstrapping Duration`. + - `Decay(Initial Target Rewards Rate, n)` if `n <= Bootstrapping Duration`. - `Final Target Rewards Rate` if `n > Bootstrapping Duration`. - The Pool Reward `Pool Reward` for an epoch index `n`, and pool `i` is calculated as follows: - Let `Pool Coefficient` be `((Pool Stake(i) << Pool Coefficient Exponent)/Total Stake) + (Validator Stake(i) << Pool Coefficient Exponent) / Total Validator Stake`. - - Since both `Pool Stake(i)` and `Validator Stake(i)` use at most 53 bits of the variable, to not overflow the - calculation, `Pool Coefficient Exponent` must be at most 11. `Pool Coefficient` will then use at most + - Since both `Pool Stake(i)` and `Validator Stake(i)` are at most `Token Supply`, to not overflow the + calculation, `Pool Coefficient Exponent` must be such that (Token Supply << Pool Coefficient Exponent)< 264. `Pool Coefficient` will then use at most `Pool Coefficient Exponent + 1` bits. - Take the `Epoch Performance Factor` for the whole epoch `n` according to [Epoch Performance Factor](#epoch-performance-factor). - - Let `Scaled Pool Reward` be `Pool Coefficient * Target Rewards Rate(n) * Epoch Performance Factor`. - - Since `Pool Coefficient` uses at most 12 bits, `Target Rewards Rate(n)` uses at most 41 bits, and - `Epoch Performance Factor` uses at most 8 bits, this multiplication will not overflow using uint64 variables. - - Finally, `Pool Reward` will be - `((Scaled Pool Reward/Validation Blocks Per Slot) >> (Pool Coefficient Exponent + 1))`. Note that if this value is - smaller than `Fixed Cost`, the validator will not receive rewards from this epoch. This is done to incentivize - validators to define reasonable values for their fixed cost. + - To calculate `Pool Reward`, we first calculate `res = (Pool Coefficient * Target Rewards Rate(n))>>PoolCoefficientExponent`. Then, `Pool Reward = ((res * Epoch Performance Factor)/Validation Blocks Per Slot)>>1`. + Note that if this value is smaller than `Fixed Cost`, the validator will not receive rewards from this epoch. + This is done to incentivize validators to define reasonable values for their fixed cost. ## Validator Rewards @@ -604,33 +596,37 @@ An account with a _Staking Feature_ can claim rewards in the same transaction wh transaction validation rules for removing the feature are defined in [TIP-42](../TIP-0042/tip-0042.md). Upon removal, the amount of Mana Rewards that can be claimed is defined as follows. -#### Parameters +### Parameters for Validator Rewards calculation -- Let `Profit Margin Exponent` be 8. +- Let `Profit Margin Exponent` be as defined in [TIP-49](../TIP-0049/tip-0049.md). -#### Input Values +### Input Values for Validator Rewards calculation - Let `Profit Margin(n)` be the `Profit Margin` for epoch index `n`. - Let `Pool Rewards(n)` be the `Pool Rewards` of the entry in `Claimable Rewards` with epoch index `n`. - Let `Pool Stake(n)` be the `Pool Stake` of the entry in `Claimable Rewards` with epoch index `n`. - Let `Fixed Cost(n)` be the `Fixed Cost` defined in the _Staking Feature_ at epoch `n`. -#### Calculations +### Validator Rewards calculation + +To calculate the claimable rewards of a validator relative to a past epoch `n`, we must first calculate `Undecayed Validator Rewards(n)`. +This value corresponds to the claimable reward if the validator claimed them right after the epoch ended. +If the claiming epoch is larger than `n+1`, this value has to be decayed to account for this epoch difference. +To calculate the `Undecayed Validator Rewards(n)` for a given epoch `n`, we proceed as follows: + +- If `Pool Rewards(n) - Fixed Cost(n) < 0`, then `Undecayed Validator Rewards(n)` is zero. +- If `Pool Rewards(n) - Fixed Cost(n) >= 0`, then `Undecayed Validator Rewards(n)` is + `Fixed Cost(n) + Profit Margin Factor + Residual Validator Factor`, where: + - `Profit Margin Factor = (Profit Margin(n) * (Pool Rewards(n) - Fixed Cost(n))) >> Profit Margin Exponent`. + - `Residual Validator Factor = ((Profit Margin Complement * (Pool Rewards(n) - Fixed Cost(n))) >> Profit Margin Exponent) * Staked Amount/Pool Stake(n)` + where `Profit Margin Complement = (1 << Profit Margin Exponent) - Profit Margin(n)`. + - Note that `((Profit Margin Complement * Pool Rewards(n)) >> Profit Margin Exponent) * Staked Amount` can use more than 64 bits. Then, to prevent overflowing, this factor should be either stored as + a 128 bits integer or it should be stored as 2 `uint64` variables (and the proper 128 by 64 division algorithm must be used). + +Finally, given `Undecayed Validator Rewards(n)`, we can calculate the decayed rewards relative to epoch `n`, by applying `Validator Rewards(Decay End Epoch, n) = Decay(Undecayed Validator Rewards(n), Decay End Epoch - n)`. + +Given the values of `Validator Rewards(Decay End Epoch, n)`, we calculate the total claimable reward for a validator as follows: -- Calculate the rewards of a validator at epoch `n` as `Rewards(Decay End Epoch, n)`: - - Calculate the `Undecayed Rewards(n)` for a given epoch `n`. - - If `Pool Rewards(n) - Fixed Cost(n) < 0`, then `Undecayed Rewards(n)` is zero. - - If `Pool Rewards(n) - Fixed Cost(n) >= 0`, then `Undecayed Rewards(n)` is - `Fixed Cost(n) + Profit Margin Factor + Residual Validator Factor`, where: - - `Profit Margin Complement = (1 << Profit Margin Exponent) - Profit Margin(n)`. - - `Profit Margin Factor = (Profit Margin(n) * (Pool Rewards(n) - Fixed Cost(n))) >> Profit Margin Exponent`. - - `Residual Validator Factor = ((Profit Margin Complement * (Pool Rewards(n) - Fixed Cost(n))) >> Profit Margin Exponent) * Staked Amount/Pool Stake(n)`. - - Note that `((Profit Margin Complement * Pool Rewards(n)) >> Profit Margin Exponent) * Staked Amount` uses up - to 94 bits and `Pool Stake(n)` up to 53, so to prevent overflowing the first factor should be either stored as - a 128 bits integer or it should be stored as 2 `uint64` variables (and the proper 128 by 64 division algorithm - must be used). - - `Rewards(Decay End Epoch, n)` is the decayed reward for epoch `n`, that is: - - `Rewards(Decay End Epoch, n) = Decay(Undecayed Rewards(n), Decay End Epoch - n)`. - Let `Future Bounded Slot Index` be given by `Commitment Index + Min Committable Age` where `Commitment Index` is the slot index of the commitment input. If no _Commitment Input_ is present, the transaction is invalid. - Note that the presence of a _Commitment Input_ is already required for any transaction containing a _Staking @@ -643,7 +639,7 @@ the amount of Mana Rewards that can be claimed is defined as follows. - `Epoch Index < Last Reward Epoch` where `Last Reward Epoch` is the minimum of `Future Bounded Epoch Index` and `End Epoch + 1`. - Let `Validator Rewards(Account ID)` be the total claimable decayed rewards for the Account Output identified by - `Account ID`. It is the sum of `Rewards(Decay End Epoch, n)` for each epoch `n` in `Claimable Rewards(Account ID)` + `Account ID`. It is the sum of `Validator Rewards(Decay End Epoch, n)` for each epoch `n` in `Claimable Rewards(Account ID)` where `Decay End Epoch` is the maximum of `Future Bounded Epoch Index - 1` (or `0` if that would underflow) and `Last Reward Epoch`. - Note: The `- 1` is applied to allow claiming the full, undecayed reward for an epoch `n - 1` in epoch `n`. @@ -656,11 +652,11 @@ for the epoch in which it is destroyed, since the rewards for that epoch only be They are _potential_ since the validator to which the output is delegating may not have been selected into the committee for that epoch. -#### Parameters +### Parameters for Delegator Rewards calculation -- Let `Profit Margin Exponent` be 8. +- Let `Profit Margin Exponent` be as defined in [TIP-49](../TIP-0049/tip-0049.md). -#### Input Values +### Input Values for Delegator Rewards calculation - Let `Profit Margin(n)` be the `Profit Margin` for epoch index `n`. - Let `Pool Rewards(n)` be the `Pool Rewards` of the entry in `Claimable Rewards(id)` with epoch index `n` for validator @@ -669,23 +665,23 @@ for that epoch. `id`. - Let `Fixed Cost(n)` be the `Fixed Cost` defined in the _Staking Feature_ at epoch `n`. -#### Calculations +### Delegator Rewards calculation -The amount of Mana Rewards that can be claimed for a _Delegation Output_ which is destroyed is defined as follows. +Similarly to the validator rewards calculation, the amount of Mana Rewards that can be claimed for a _Delegation Output_ which is destroyed is defined as follows. We begin by calculating the undecayed claimable rewards relative to a past epoch `n`, denoted by `Undecayed Delegator Rewards(n)`. +This value corresponds to the claimable reward if the delegator claimed them right after the epoch ended. +If the claiming epoch is larger than `n+1`, this value has to be decayed to account for this epoch difference. +To calculate the `Undecayed Delegator Rewards(n)` for a given epoch `n`, we proceed as follows: -- Calculate the rewards of a delegator at epoch `n` as `Rewards(Decay End Epoch, n)`: - - Calculate the `Undecayed Rewards(n)` for a given epoch `n`. - - If `Pool Rewards(n) - Fixed Cost(n) >= 0`, then `Undecayed Rewards(n)` is - `((Profit Margin Complement * (Pool Rewards(n) - Fixed Cost(n))) >> Profit Margin Exponent) * Delegated Amount/Pool Stake(n)`. - - Note that - `((Profit Margin Complement * (Pool Rewards(n) - Fixed Cost(n))) >> Profit Margin Exponent) * Delegated Amount` - uses up to 94 bits and `Pool Stake(n)` up to 53, so to prevent overflowing the first factor should be either - stored as a 128 bits integer or it should be stored as 2 uint64 variables (and the proper 128 by 64 division - algorithm must be used). - - If `Pool Rewards(n) - Fixed Cost(n) < 0`, then `Undecayed Rewards(n)` is +- If `Pool Rewards(n) - Fixed Cost(n) < 0`, then `Undecayed Delegator Rewards(n)` is `((Profit Margin Complement * Pool Rewards(n)) >> Profit Margin Exponent) * Delegated Amount/Pool Stake(n)`. - - `Rewards(Decay End Epoch, n)` is the decayed reward for epoch `n`, that is: - - `Rewards(Decay End Epoch, n) = Decay(Undecayed Rewards(n), Decay End Epoch - n)`. +- If `Pool Rewards(n) - Fixed Cost(n) >= 0`, then `Undecayed Delegator Rewards(n)` is + `((Profit Margin Complement * (Pool Rewards(n) - Fixed Cost(n))) >> Profit Margin Exponent) * Delegated Amount/Pool Stake(n)`. + - Note that `((Profit Margin Complement * Pool Rewards(n)) >> Profit Margin Exponent) * Delegated Amount` can use more than 64 bits. Then, to prevent overflowing, this factor should be either stored as + a 128 bits integer or it should be stored as 2 `uint64` variables (and the proper 128 by 64 division algorithm must be used). + +Finally, given `Undecayed Delegator Rewards(n)`, we can calculate the decayed rewards relative to epoch `n`, by applying `Delegator Rewards(Decay End Epoch, n) = Decay(Undecayed Delegator Rewards(n), Decay End Epoch - n)`. +Given the values of `Delegator Rewards(Decay End Epoch, n)`, we calculate the total claimable reward for a delegator as follows: + - Let the `Claimable Rewards(address)` be all reward entries for the validator identified by the Account ID corresponding to the `address`, which is the `Validator Address` field in the Delegation Output, where the entry's epoch index `Epoch Index` satisfies `Epoch Index >= Start Epoch` and `Epoch Index <= Delegation End`, where: @@ -699,7 +695,7 @@ The amount of Mana Rewards that can be claimed for a _Delegation Output_ which i of the previous epoch became available, thus forfeiting the potential rewards of that previous epoch. - If the output is in _Delayed Claiming State_ let `Delegation End` be `End Epoch`. - Let `Delegator Rewards(Delegation ID)` be the total claimable decayed rewards for the Delegation Output identified by - `Delegation ID` with `address` set to the `Validator Address`. It is the sum of `Rewards(Decay End Epoch, n)` for each + `Delegation ID` with `address` set to the `Validator Address`. It is the sum of `Delegator Rewards(Decay End Epoch, n)` for each epoch `n` in `Claimable Rewards(address)`, where `Decay End Epoch` is the maximum of `Future Bounded Epoch Index - 1` (or `0` if that would underflow) and `Delegation End`. - Note: The `- 1` is applied to allow claiming the full, undecayed reward for an epoch `n - 1` in epoch `n`. @@ -731,7 +727,7 @@ output only needs to contain the minimum storage deposit. The remaining funds ca delegate for `X+1`, which can repeat this procedure. In this manner, one can delegate for one epoch at a time and never lose out on any rewards. The following figure exemplifies this procedure. -![](./assets/delayed-claiming.png) +![Example of delayed claiming](./assets/delayed-claiming.png) Delayed Claiming also allows for a high degree of liquidity while delegating. Even without delayed claiming, this delegation mechanism implements _liquid delegation_ as Delegation Outputs are never locked and can be accessed anytime. @@ -751,7 +747,7 @@ This figure showcases how epochs are set when creating and transitioning Delegat epochs in slots is not accurately depicted here. What matters for epoch setting is 1) what the current epoch is and 2) whether the creation or transition happens before or after the registration slot for the following epoch. -![](./assets/delegation-epochs.png) +![How epochs are set when creating and transitioning Delegation Outputs](./assets/delegation-epochs.png) - Delegation Output X is created before the end of the Registration Slot. Therefore its `Start Epoch` is set to `21`, as that is the earliest epoch for which it could receive rewards. However, it is also transitioned before the end of the