Skip to content

Commit

Permalink
Add backdating blocks explanation & figures
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippGackstatter committed Nov 7, 2023
1 parent e1f9228 commit 1dfb036
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 3 deletions.
Binary file added tips/TIP-0038/assets/backdating-blocks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
Binary file added tips/TIP-0038/assets/expiration-uc-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 42 additions & 3 deletions tips/TIP-0038/tip-0038.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ the state forward. The **state can be updated according to the transition rules
its current state**. As a consequence, each such output has a unique successor, and together they form a path or _chain_
in the graph induced by the UTXO spends. Each chain is identified by its globally unique identifier.

![](chain-constraint.png)
![](./assets/chain-constraint.png)

Account outputs, foundry outputs, and NFT outputs all use this chain constraint concept and define their own unique
identifiers.
Expand Down Expand Up @@ -960,15 +960,20 @@ follows:

## Expiration Unlock Condition Index Bounds

In theory, the choice of bounded slot indices on the _Expiration Unlock Condition_ is ideal when the `Address` and
In theory, the conditions for a successful unlock on the _Expiration Unlock Condition_ are ideal when the `Address` and
`Return Address` pick the commitment most suitable to them, i.e. the oldest (`Maximum Committable Age` old) and newest
(`Min Committable Age` old) one, respectively. In practice, however, it is likely that a node will provide a commitment
within the range of maximum and minimum committable age. If both pick the same commitment this causes a period of time
("deadzone") where neither `Address` nor `Return Address` can unlock the output with the expiration unlock condition.
However, this deadzone is more desirable than the alternative, where for some overlapping period of time, both `Address`
and `Return Address` would be able to unlock the output, potentially allowing a double spend.

**Example with optimal Commitment Input choice**
![](./assets/expiration-uc-example.png)

_In this figure, Block A and B are issued in the slot corresponding to the current Wall Clock Time respectively (which
is not globally the same in this example). It shows how the choice of the commitment affects the unlocking outcome._

**Example with optimal Commitment Input choices**

Suppose that `Minimum Committable Age` is 3 and `Maximum Committable Age` is 10, and there is an Expiration Unlock
Condition with `Slot Index` set to 20. Note the restrictions on the Commitment Input within a transaction relative to a
Expand All @@ -983,6 +988,40 @@ If however, the current slot is 18, and both owners would use the same Commitmen
of 8 and 15 of possible commitments, then neither one of them can unlock the output, as neither 20 > 13+10 nor 20 <=
13+3 is true.

**Backdating blocks**

One variable that was not mentioned yet is how a client can set a block's `Issuing Time`, relative to which the chosen
commitment is validated, which allows for _backdating_ blocks. Backdating blocks by a singificant amount is only
possible when there is liveness. The most that someone can backdate a block is to
`Accepted Tangle Time - Liveness Threshold Upper Bound`, so if there is liveness (`ATT ~= Wall Clock Time`), then the
most someone could backdate their block is by `Liveness Threshold Upper Bound`.

![](./assets/backdating-blocks.png)

_This figure shows an example of backdating a block by one slot (which is less than `Liveness Threshold Upper Bound`).
The global Wall Clock Time is the same for both blocks and yet both transactions in their respective blocks could unlock
the output._

The only time that backdating has any consequence is if there is liveness. Assume some application (for example, a layer
2 chain) relies on an expired output being consumed. The application should only consider the expired output as consumed
and act on that if the output is at least accepted, but ideally until it is committed, confirmed or finalized. The
higher the level of finality the application waits for, the more difficult it is for the `Address` owner (the receiver
of the output with an _Expiration Unlock Condition_) to backdate a block and revert the consumption of the expired
output. For example, if the application waits for commitment of the expired output being consumed, then it is impossible
for the receiver address to subsequently consume it, unless it forces a chain switch, because the receiver address can
only consume the output in an earlier slot than the return address can consume it, and all such earlier slots are
already committed. If the application only waits for acceptance of the expired output consumption, a malicious owner of
the receiver address could technically issue a backdated block shortly after `ATT - Liveness Threshold Upper Bound`, but
this block would be less likely to be selected as a tip, and because the majority of online validators already accepted
the expired output consumption, they should not accept the backdated receiver consumption because it is a conflict. The
only way the receiver address could revert the other conflict is by having support of a majority of other validators to
revert it. In conclusion, it is very difficult to backdate even with just acceptance, and becomes more difficult when
waiting for higher levels of finality. This attack relates to the fundamental fact that the best approximation of time
is the block's `Issuing Time` timestamp, which is is meant to be very difficult to falsify.

**Note**: An IOTA Smart Contract Chain is not susceptible to such a backdating attack anyway because it is the receiver
address of the expiration locked output and it is _not_ waiting for the output to expire in order to consume it.

# Copyright

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

0 comments on commit 1dfb036

Please sign in to comment.