Difficulty
Difficulty is a measure used to keep block production at a constant rate, it is the average amount of hashes before a solution is found.
Checking A Block's Proof Of Work
To check a block's PoW hash
you interpret the hash as a little endian integer and multiply it by the difficulty, if the result
does not overflow the hash is valid1:
\(Hash * difficulty <= MAXu256 \)
Calculating Difficulty
To calculate difficulty, Monero keeps a window of the last 7352 timestamps and cumulative difficulties, if there are not enough blocks, then you just use as many as possible.
The genesis block is skipped for these calculations3 so should not be included in the timestamp / CD list but it is included in the cumulative difficulty of the chain.
If the amount of blocks is less than or equal to 1 then 1 is returned as the difficulty4.
The timestamps and cumulative difficulties are then shortened to 7205 blocks so that calculations lag 15 blocks behind the chain.
The timestamps are then sorted, in ascending order. We now need to get a time span value to do this we first remove the outliers:
If the number of timestamps is less than or equal to the amount of blocks we are accounting for (600: 720 - 2 * 60) then the lower is set to 0 and the upper is set to the length of timestamps. Otherwise, if we have enough timestamps, the lower and upper is calculated by6:
\(lower = \frac{len(timestamps) - 600+1}{2} \)
\(upper = lower + 600 \)
We then get the timestamp at position lower
and take this away from the timestamp at position upper -1
to get timeSpan
.
If timeSpan
is 0 we set it to 17.
We also get the cumulative difficulty at position lower
and take this away from the cumulative difficulty at position upper -1
to get totalWork
.
The next difficulty is then calculated by8:
\(difficulty = \frac{totalWork * targetSeconds + timeSpan -1}{timeSpan} \)
Target Seconds
For hard-fork v1 the target seconds is 60, so one block a minute. For hard-fork 2 onwards block time is 1209.