Skip to content

Commit

Permalink
minors updates in all the doc
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviasaa committed Mar 24, 2024
1 parent 9fd519d commit 98ab0ca
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 68 deletions.
26 changes: 26 additions & 0 deletions tips/TIP-0039/constraints.md
Original file line number Diff line number Diff line change
@@ -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)`< <code>2<sup>32</sup></code> (which is equivalent, by contruction to 0≤`Decay Factors Exponent`≤3),
- `slotIndexDiff * Generation Rate`< <code>2<sup>32</sup></code>,
- `Decay Factor Epochs Sum * Generation Rate`< <code>2<sup>32</sup></code>,


TO DO: Rewards and maximum theoretical Mana in the system is smaller than <code>2<sup>Bits Count</sup> - 1</code>
137 changes: 69 additions & 68 deletions tips/TIP-0039/tip-0039.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).

Expand Down Expand Up @@ -155,12 +155,6 @@ code.
Defines fixed potential Mana generation per slot.
</td>
</tr>
<tr>
<td><code>Δ</code></td>
<td>
The duration of an epoch in years.
</td>
</tr>
</table>

Additionally, we use the protocol parameters, as defined in [TIP-49], and `Decay Factors Length`, defined as the length
Expand Down Expand Up @@ -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 <code>2<sup>Decay Factors Exponent</sup>Decay per
Epoch<sup>n</sup></code>, 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.
Epoch<sup>n</sup></code>, 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
Expand All @@ -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,
Expand All @@ -232,16 +228,14 @@ necessarily corresponds to the `epochIndexDiff`<sup>th</sup> 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
Expand All @@ -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 <code>Decay per Epoch</code> 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
Expand Down Expand Up @@ -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 <code>2<sup> `32`</sup></code> 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):

Expand Down Expand Up @@ -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 |
| ----------------------------- |
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 98ab0ca

Please sign in to comment.