Calculate Delegation End Epoch from the Future Bounded Commitment Index #509
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Calculate the end epoch for a delegation output from the future bounded commitment input slot index.
Consider this example for why this is necessary: Suppose we created a Delegation Output in Epoch 2, which means we set Start Epoch to 3 (the first epoch for which we delegated) and now we want to stop delegating and claim the rewards for epoch 3. Note that rewards become available with the commitment of the last slot of an epoch. So the rewards for epoch 3 become available when the last slot of epoch 3 is committed, which happens at some point at the beginning of epoch 4.
If we issue the block containing the claiming transaction at the beginning of epoch 4 and happen to pick exactly the slot in which rewards became available as a commitment input, then the corresponding epoch of that slot is 3 and due to the subtraction of 1 epoch (to account for the fact that we cannot be claiming rewards for the "current epoch" since it hasn't finished yet), we would end up requesting the rewards for delegation start = 3 and end = 2, which always yields 0.
This reward 0 would be injected as context to the VM while a client might have calculated it correctly by adding MinCA to the commitment input, which results in an undesirable discrepancy.
To rectify this, we can simply add MinCA to the commitment input slot index, which would result in the end epoch set to 3, because
epochForSlot(lastSlotOfEpochX + MinCA) = X+1
. At the same time, with this calculation we can never end up claiming rewards for an epoch x+1 when issuing a block in epoch x, since it's impossible to pick a commitment that is newer than Min CA, which is the desirable behavior.Mostly unrelated but for completeness: A similar problem still exists if we make less strict assumptions like that we cannot pick the optimal commitment, i.e. one that is more than Min CA old. Then we could still issue a block in epoch 5 and have
epochFromSlot(commitment index + Min CA)
end up as epoch 4. But using Min CA here is a necessary trade-off to prevent anyone from faking the future, e.g. issue a block in epoch 4 but have the calculated epoch index end up as epoch 5. More on this: https://github.com/iotaledger/tips/blob/tip40/tips/TIP-0040/tip-0040.md#time-boundaries.