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 Blocks Proof Of Work

To check a blocks 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 that 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.