In order to explain the logic of difficulty adjustment, we will use the go implementation of Ethereum which is generally called Geth. Source code of Geth can be found here.
Difficulty adjustment algorithm is coded in in block_validator.go file, which can be found here.
By difficulty adjustment we mean the logic in Ethereum using which Ethereum tries to keep mining time of the blocks between 10 to 19 sec. If difference in mining time is between 0 to 9 sec. then Geth tries to increase the difficulty to mine the block and if difference is 20 sec. or more, then Geth tries to reduce the mining difficulty of the system.
In block_validator.go file, function CalcDifficulty is called to adjust the difficulty of the system and it returns the difficulty of the next block when it will be created. This function, in return, calls calcDifficultyHomestead or calcDifficultyFrontier depending on the configuration parameters. Latest version of Ethereum uses calcDifficultyHomestead function, therefore we will be reviewing calcDifficultyHomestead function.
In order to calculate the difficulty of the new block, this function needs following input parameters:
time – Proposed time of formation of new block
parentTime – Time of formation of parent Block
parentNumber – Parent block, block number.
parentDiff – Difficulty of parent block
Below is step by step process how difficulty of new block gets created.
1. First, difference between time of formation of parent block and new block is calculated.
2. Output of step 1 is then divided by 10 and integer of it is stored. This is done to create ranges. If output of step 1 is between 1 – 9 then output of this step will be 0. If output of step 1 is between 10 – 19 then output of this step will be 1. If output of step 1 is between 20 – 29 then output of this step will be 2 and so on.
3. From step above various ranges gets created. Now in order to create three ranges we will subtract 1 from output of step 2. The three ranges will be either +ve, zero or –ve. If you see it carefully then output of this step will be +ve when output of step 1 is between 0 – 9, zero when output of step 1 is between 10 – 19 and –ve when output of step 1 is anything more than 20.
4. Now compare output of previous step with -99 and if it is even lesser than -99 then set it as -99. This is done to limit the smallest possible value of step 3, otherwise keep the value of output of previous step as is.
5. Next we divide the parent block difficulty by the difficulty bound divisor, whose value is 2048.
6. Multiply output of step 4 with step 5. This will give the difference of difficulty of new block with old parent block. Depending is this value is +ve then difficulty will increase and if this value is –ve then then new difficulty will decrease.
7. Now add output of step 6 to parent difficulty and result will be the difficulty of the new block.
8. Once difficulty is calculated, a check is made to make sure that difficulty calculated is at least more than the minimum threshold value of 131072.
9. Before returning the difficulty, check is done that if block number is more than 200,000 then “The Bomb” logic is applied to increase the difficulty exponentially.
10. In order to increase the difficulty exponentially, new block number is calculated by adding one to the parent block number.
11. Now new block number is divided by 100,000.
12. If new block number is more than 200,000 then output of step 11 is subtracted from 2.
13. Now exponentially increased difficulty delta is calculated by doing following calculation: 2 ^ output of step 12.
14. And new difficulty is calculated by adding output of previous step to the difficulty calculated in step 7.
So, this is basically how Ethereum tries to keep the mining time difference between 10 – 19 seconds. Now, if we carefully take a look to step 2, then we will observe that division by 10 helps to create three ranges. If the value falls in first range then difficulty is increased, if value falls in second range then difficult is kept constant and finally, if the range falls in third range then difficulty is reduced.
Now if we want to change the ranges of difficulty, we can do it by dividing it by some another number in step 2. That means, if we want to keep mining time difference in between 0 – 4 sec. then increase the difficulty, if mining time difference is between 5 – 9 sec. then keep the difficulty constant and if mining time is 10 or more sec. then try to reduce the difficulty, then instead of dividing by 10 you can divide the value by 5 in step 2. This way you can easily manage the ranges of mining difficulty.
Below is the graph showing Ethereum main network block difficulty growth.
As of 25 February 2017
This work is combined effort of Ajay Singh and Neeraj S Srivastava