The explanations on the web are all very vague and mystical, on purpose maybe. Here is my take in simple words, just reading the megacoin source code from the above comment.
The goal is to have a more adaptive way of adjusting the difficulty instead of just averaging the last 2016 blocks like bitcoin. This is needed because of multipools which might switch the coin they are mining, and a sudden change in hashrate can occur (both increasing or decreasing). Especially when a multipool switches away you get stuck too long with a too high difficulty.
The algo loops backwards through the blocks, starting from the current one. The PastBlocksMass
is just the number of blocks, so it starts at one and increases in each loop.
In each loop an adjustment factor is computed, which is the target block time divided by the actual block time, in a cumulative fashion, so at loop 10 we would have the 25 minutes target time divided by the time it actually took to compute the last ten blocks. When the hashrate increases, we get shorter times and an adjustment factor greater than one and vice versa.
The loop ends whenever the average adjustment factor is larger than the kimoto-value
, or smaller than 1/kimoto-value
. To understand this look at this python script and an example plot:
from pylab import *
one_day = 1440 / 2.5 # how many 2.5 min blocks per day
nmin = one_day / 4 # PastBlocksMin
nmax = one_day * 7 # PastBlocksMax
x = arange(nmin, nmax) # PastBlocksMass
# start with 2.5 minute blocktime + some noise
t0 = 2.5 + randn(nmax) / 4
t1 = 2.5 + randn(nmax) / 4
# t0 has 20% more hashrate, so shorter blocktime in the beginning
t0[:one_day] = 2.5 / 1.2 + randn(one_day) / 4
# t1 has higher blocktime in the beginning
t1[:one_day] = 2.5 / 0.9 + randn(one_day) / 4
s = arange(nmax)
adjust0 = (arange(1, nmax + 1) * 2.5 ) / cumsum(t0)
adjust1 = (arange(1, nmax + 1) * 2.5 ) / cumsum(t1)
# the magic function
def kimoto(x):
return 1 + (0.7084 * pow((double(x)/double(144)), -1.228));
plot(x/one_day, kimoto(x))
plot(x/one_day, 1/kimoto(x))
plot(s/one_day, adjust0)
plot(s/one_day, adjust1)
legend(["kimoto","1/kimoto", "20% increase in hashrate", "10% drop in hashrate"])
xlabel("days")
ylabel("adjustment factor (target/actual blocktime)")
show()
The script produces a figure like this .
It shows two constructed examples when the hashrate increases and when it drops for one day. Best is to play with different settings for a while to get a feel for what is going on.
You see that the lines cross through the Kimoto formula at some point. This is when the algo exits and uses this adjustment factor to compute a new target/difficulty. For large adjustment factors this happens earlier than for the ones closer to one. This is to have a quick adaptation if the hashrate changes a lot, and a slower one if not - then we want a longer period to get a better average. The parameters of the Kimoto formula are adjusted in such a way that one roughly adjusts in one day to a 10% change and in seven days to a 1.2% change. A minimum of 144 blocks determine the new difficulty and at most 4032 (0.25 days or 7 days for a 2.5 minute blocktime).
Summary: the Kimoto gravity well algo has a fancy name and determines the number of blocks which contribute to the evaluation of the new difficulty. It gives fewer blocks for high hashrate changes and is therefore more adaptive.