``````    block_diff = parent_diff + parent_diff // 2048 *
max(1 - (block_timestamp - parent_timestamp) // 10, -99) +
int(2**((block.number // 100000) - 2))
``````

where // is the integer division operator, eg. 6 // 2 = 3, 7 // 2 = 3, 8 // 2 = 4.

How does this work?

(This question was prompted by the question What was the first block mined with Homestead?)

Other related Q&As:

## Summary

If the timestamp difference `(block_timestamp - parent_timestamp)` is:

• < 10 seconds, the difficulty is adjusted upwards by `parent_diff // 2048 * 1`
• 10 to 19 seconds, the difficulty is left unchanged
• >= 20 seconds, the difficulty is adjust downwards proportional to the timestamp difference, from `parent_diff // 2048 * -1` to a max downward adjustment of `parent_diff // 2048 * -99`

This is consistent with the statement from ethdocs.org - Ethereum Homestead - The Homestead Release:

EIP-2/4 eliminates the excess incentive to set the timestamp difference to exactly 1 in order to create a block that has slightly higher difficulty and that will thus be guaranteed to beat out any possible forks. This guarantees to keep block time in the 10-20 range and according to simulations restores the target 15 second blocktime (instead of the current effective 17s).

And from Ethereum Network Status, the average block time currently is 13.86 seconds.

## Details

``````    block_diff = parent_diff + parent_diff // 2048 *
max(1 - (block_timestamp - parent_timestamp) // 10, -99) +
int(2**((block.number // 100000) - 2))
``````

where // is the integer division operator, eg. 6 // 2 = 3, 7 // 2 = 3, 8 // 2 = 4.

can be broken down into the following parts:

Sub-formula B - The difficulty bomb part, which increases the difficulty exponentially every 100,000 blocks.

``````+ int(2**((block.number // 100000) - 2))
``````

The difficulty bomb won't be discussed here as it is already covered in the following Q&As:

Sub-formula A - The difficulty adjustment part, which increases or decreases the block difficulty depending on the time between the current block timestamp and the parent block timestamp:

``````+ parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)
``````

Subformula A1 - Lets separate out part of Subformula A

``````+ max(1 - (block_timestamp - parent_timestamp) // 10, -99)
``````

and consider what the adjustment effect is due to the timestamp difference between the current block and the parent block:

When `(block_timestamp - parent_timestamp)` is

• 0, 1, 2, ..., 8, 9 seconds
• A1 evaluates to `max(1 - 0, -99) = 1`
• A evaluates to `+parent_diff // 2048 * 1`
• 10, 11, 12, ..., 18, 19 seconds
• A1 evaluates to `max(1 - 1, -99) = 0`
• A evaluates to `+parent_diff // 2048 * 0`
• 20, 21, 22, ..., 28, 29 seconds
• A1 evaluates to `max(1 - 2, -99) = -1`
• A evaluates to `+parent_diff // 2048 * -1`
• 30, 31, 32, ..., 38, 39 seconds
• A1 evaluates to `max(1 - 3, -99) = -2`
• A evaluates to `+parent_diff // 2048 * -2`
• 1000, 1001, 1002, ..., 1008, 1009 seconds
• A1 evaluates to `max(1 - 100, -99) = -99`
• A evaluates to `+parent_diff // 2048 * -99`
• > 1009 seconds
• A1 evaluates to `max(1 - {number greater than 100}, -99) = -99`
• A evaluates to `+parent_diff // 2048 * -99`

So, if the timestamp difference `(block_timestamp - parent_timestamp)` is:

• < 10 seconds, the difficulty is adjusted upwards by `parent_diff // 2048 * 1`
• 10 to 19 seconds, the difficulty is left unchanged
• >= 20 seconds, the difficulty is adjust downwards proportional to the timestamp difference, from `parent_diff // 2048 * -1` to a max downward adjustment of `parent_diff // 2048 * -99`

## The Source Code

``````func calcDifficultyHomestead(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki
// algorithm:
// diff = (parent_diff +
//         (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
//        ) + 2^(periodCount - 2)

bigTime := new(big.Int).SetUint64(time)
bigParentTime := new(big.Int).SetUint64(parentTime)

// holds intermediate values to make the algo easier to read & audit
x := new(big.Int)
y := new(big.Int)

// 1 - (block_timestamp -parent_timestamp) // 10
x.Sub(bigTime, bigParentTime)
x.Div(x, big10)
x.Sub(common.Big1, x)

// max(1 - (block_timestamp - parent_timestamp) // 10, -99)))
if x.Cmp(bigMinus99) < 0 {
x.Set(bigMinus99)
}

// (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
y.Div(parentDiff, params.DifficultyBoundDivisor)
x.Mul(y, x)

// minimum difficulty can ever be (before exponential factor)
if x.Cmp(params.MinimumDifficulty) < 0 {
x.Set(params.MinimumDifficulty)
}

// for the exponential factor
periodCount.Div(periodCount, ExpDiffPeriod)

// the exponential factor, commonly referred to as "the bomb"
// diff = diff + 2^(periodCount - 2)
if periodCount.Cmp(common.Big1) > 0 {
y.Sub(periodCount, common.Big2)
y.Exp(common.Big2, y, nil)
}

return x
}
``````
• @BookyPooBah Thanks for a detailed walk-through. In your explanation for subformula A and A1, for `20-29` seconds and `30-39` seconds, isn't the result of A1 `-1` and `-2` respectively? Jul 13, 2016 at 15:44
• Okay this makes sense, essentially you're looking at the timestamp difference from the last 2 blocks and you're extracting the 2nd significant digit. That digit is the determining factor whether blocks are too slow, too fast or just right. Can you explain the `2048` magic number though? What's the idea behind dividing it by `2048` and why that number? Aug 7, 2016 at 23:18
• @BokkyPooBah I love that you gave yourself the time to write this detailed account: I learned from it. I want to add the following: github.com/ethereum/go-ethereum/blob/… No matter how poor is your hashrate, there is a minimum you cannot go under. github.com/ethereum/go-ethereum/blob/… Jan 25, 2017 at 15:45
• The ranges used in the summary do not contain `(19,20)` range. Jun 26, 2017 at 9:39
• @greatwolf it's a difficulty bound divisor, had it been smaller, the incentives wouldn't work out Sep 21, 2018 at 19:38

Ethereum's algorithm would have been better if the max() had not been used. The parent_diff/2048*(1-t/10) could have been expanded to prevent the zero that results from integer division. This would have resulted in

diff = parent_diff + parent_diff/N - parent_diff*t/T/N

where t = parent solvetime T = target solvetime N = extinction coefficient aka "mean lifetime" aka number of block to "temper" or "buffer" the size of the response. It can't be too small or a negative difficulty can result from long solvetimes.

This is very close to the theoretically best algorithm which is an exponential moving average (EMA) that I and others have investigated. It's an approximation of the EMA by the taylor series expansion of the exponential function:

e^x = 1 + x + x^2/2! + ...

Where you use the approximation e^x = 1 + x in the EMA algorithm:

diff = parent_diff*( 1 - A + A*T/t )

where A = alpha = 1-e^(-t/T/N)

This algorithm was discovered by Jacob Eliosoff who was already very familiar with EMA's for stock prices. He needed to modify it to fit difficulty, and the result turns out to be a known version that's mentioned in Wikipedia in regards to estimating computer performance:

https://en.wikipedia.org/wiki/Moving_average#Application_to_measuring_computer_performance

I say it's theoretically best because you can reduce N all the way down to "1" and the mean and median solvetimes are close to the expected T and ln(2)*T. So it's the best estimator (I know of) of guessing the current hashrate based on only the previous block.