|
| 1 | +# Principles |
| 2 | + |
| 3 | +This section contains general principles to apply when developing Cardano nodes. |
| 4 | + |
| 5 | +## Optimise only for the worst case |
| 6 | + |
| 7 | +Algorithms often possess different performance characteristics in the best, |
| 8 | +average and worst cases. Quick sort has, for example, `O(n*log(n))` time |
| 9 | +complexity in the average case, but `O(n^2)` in the worst case. |
| 10 | + |
| 11 | +Often in software we are interested in optimising for the average case, since |
| 12 | +over time it tends to result in the highest overall performance. In Cardano, |
| 13 | +however, we take a different approach: we want to only optimise the worst case |
| 14 | +performance, and indeed, pick algorithms where _worst case is the same as best |
| 15 | +(or average) case_. |
| 16 | + |
| 17 | +### Motivation |
| 18 | + |
| 19 | +There are two motivating ideas behind this principle: |
| 20 | + |
| 21 | +1. _Performance will come to be relied upon_. This is an instance of Hyrum's |
| 22 | + law in action: |
| 23 | + |
| 24 | + > With a sufficient number of users of an API, it does not matter what you |
| 25 | + > promise in the contract: all observable behaviors of your system will be |
| 26 | + > depended on by somebody. |
| 27 | +
|
| 28 | + If we manage to increase average performance, tools will be developed that |
| 29 | + come to expect this behaviour. If blocks can be processed faster, for |
| 30 | + example, there may be pressure to use that extra time to allow larger script |
| 31 | + execution budgets. |
| 32 | + |
| 33 | +1. Forcing honest nodes to do more work provides an attack opportunity for the |
| 34 | + adversary. In the worst case, an adversary could potentially force nodes to |
| 35 | + fail to adopt or forge blocks, and hence potentially gain control of the |
| 36 | + chain. |
| 37 | + |
| 38 | +### Example: UTxO locality |
| 39 | + |
| 40 | +As an example, there is certain evidence that the UTxO set exhibits a degree of |
| 41 | +temporal locality. That is, there are a number of long-lived UTxO entries that |
| 42 | +are unlikely to be spent, while recently created entries are quite likely to |
| 43 | +come up again. |
| 44 | + |
| 45 | +We could choose to take advantage of this to organise the UTxO along the form |
| 46 | +of a LRU (least recently used) cache. This would likely speed up UTxO lookup |
| 47 | +in the average case, particularly were the UTxO stored on disk. |
| 48 | + |
| 49 | +However, an attacker could then choose to deliberately craft a number of |
| 50 | +transactions containing UTxO that were created a long time ago. A block filled |
| 51 | +with such transactions, while being perfectly legitimate, might take |
| 52 | +significantly longer to process than a regular block. The attacker could use |
| 53 | +this delay to gain an advantage in block forging and thus magnify their |
| 54 | +effective stake. |
| 55 | + |
| 56 | +### Considerations |
| 57 | + |
| 58 | +Whilst we have written the above as a general principle, there are of course |
| 59 | +various considerations that effect how much we want to follow it: |
| 60 | + |
| 61 | +1. The situation we most want to avoid is where an attacker could control an |
| 62 | + input such that they can force the worst-case behaviour. The UTxO locality |
| 63 | + example above is one such. |
| 64 | +1. Still problematic are cases where an attacker cannot control the performance |
| 65 | + but can predict it, or less serious still, observe it. Either way a |
| 66 | + prepared attacker could take advantage of the degraded performance to launch |
| 67 | + an attack on the chain. |
| 68 | +1. Either of these cases are exacerbated if the same behaviour is coordinated |
| 69 | + across all nodes, since this allows an attacker to exploit a performance |
| 70 | + drop across the entire network. |
| 71 | + |
| 72 | +In situations where the inputs to a function are random or not observable by |
| 73 | +an adversary, or where the effects are purely local, it may therefore still be |
| 74 | +sensible to optimise for the average case. An example of such might be in |
| 75 | +local state query computations, since these are triggered only by a (trusted) |
| 76 | +local connection and do not lie on a critical path for block forging or |
| 77 | +adoption. |
| 78 | + |
| 79 | +The key point is that, in the Cardano setting, optimisations should be carefully |
| 80 | +considered and it is certainly not the case that better average-case performance |
| 81 | +is always desirable! |
0 commit comments