# How can I calculate network hashrate for a given range of blocks where difficulty changes somewhere within the range?

Not sure if the title is poorly worded, but here's what I'm looking to do.

If I have a range of blocks and I want to calculate the hashrate, I can do something similar to what is found here.

To take it a step further, I'd like to be able to calculate hashrate for a given number of blocks from the current block. Using the example provided above, this is rather trivial.

However, I'm running into issues doing this when the difficulty changes somewhere within the range of blocks.

Take last night as an example. Difficulty changed to roughly ~390M. Prior to that it was roughly ~267M.

How would I go about calculating an average network hashrate for a given range where the difficulty has changed within that range?

Thank you for the help!

## 2 Answers

Start by computing the total amount of work. Work is defined as the expected number of hashes that were necessary for a particular block. If a block's target is `Target`, its amount of work is `Work = 2**256 / (Target + 1)` (follows from the fact that `Target + 1` in `2**256` hashes have a value lower or equal to `Target`). As the difficulty `Diff` is defined as `MaxTarget / Target` with `MaxTarget = 65535 * 2**208`, it follows that `Work = Diff * 2**48 / 65535 = Diff * 4295032833`.

So, for each block, look at its difficulty, and compute `Diff * 4295032833`. Compute the sum of all those values for all blocks in your time range.

Now divide that sum-work by the number of seconds your interval lasted. The result is your average number of hashes per second during that interval.

For very short intervals (less than a few hours), it is possible for block timestamp inaccuracy to be relevant. One way to avoid this problem is by starting off not with a range of blocks, but a range of timestamps, and choosing all blocks within that range, rather than estimating the time range from the range blocks.

You can look at the range's first and last block, if they match exactly you can just calculate the average hash-rate from time elapsed, height difference (number of blocks) and difficulty.

If they don't match, you will have to create the weighted average over each difficulty section. You calculate the average hash-rate for each section then multiply it with the duration, add all the results together, divide by total time.

You could find the sections by binary search between your range's first block and last block, but it would be much easier to just look at every 2016th block, because the reset happens on schedule. ;)

Better yet, you can actually tell immediately that way how many changes in difficulty exist in your range by looking at the height of first and last block.

Update:
As pointed out by Pieter, it is possible for blocks to be timestamped inconsistently, making it possible for a block to have a lower timestamp than their predecessor. Any implementation should probably check for corner-cases such as this one. In general the result will be better if a larger interval is taken into account, unless the interval is so large that the hashing-power has increased significantly within it.

• This will deal badly with cases where time goes backwards between two blocks. – Pieter Wuille Apr 26 '14 at 11:54