DGW (Dark Gravity Wave) Problems
zawy12 opened this issue · 0 comments
zawy12 commented
Dark Gravity Wave problems:
- The complicated core [code] in the main loop is just a simple moving average of the targets that gives double weight to the most recent target, which is just an error (see math below).
- It uses 1 less timestamp than it is supposed to [code] causing it to have a 1/24 longer avg solvetime than expected when N=24.
- By having a small N=24, there is an additional 1.5% avg longer solvetime error. This is from solvetimes being more likely to be fast than slow (the Erlang or gamma is the distribution for N samples of the exponential distribution).
- Timespan limits 3x and 1/3 [code] allow a selfish mine to get unlimited blocks in 2x the averaging window if the timestamps are not sequential or otherwise limited in the allowed range. See timestamp attacks article.
2 and 3 cause solvetime to be 6% longer than expected.
# Simple moving average difficulty algorithm
# timestamps[1] = most recent timestamp
next_target = average(N past targets) * (timestamps[1]-timestamps[N+1])/(N*desired_block_time)
Instead of average of past N targets, DGW does this:
# Dark gravity wave "average" Targets
avgTarget = Target[1];
for ( i=2 ; i <= N; i++) {
avgTarget = ( avgTarget*i +Target[i] ) / (i+1) ;
}
There's nothing in the comments to explain what this is supposed to be doing, so I expanded it out for i =2 to 4 (N=4). Target[1] = T1 = previous block's target and T4 is 4th block in the past.
which simplifies to:
This is just an average that gives double weight to the most recent target.
Here's the actual code.
for (unsigned int nCountBlocks = 1; nCountBlocks <= nPastBlocks; nCountBlocks++) {
arith_uint256 bnTarget = arith_uint256().SetCompact(pindex->nBits);
if (nCountBlocks == 1) {
bnPastTargetAvg = bnTarget;
} else {
// NOTE: that's not an average really...
bnPastTargetAvg = (bnPastTargetAvg * nCountBlocks + bnTarget) / (nCountBlocks + 1);
}
if(nCountBlocks != nPastBlocks) {
assert(pindex->pprev); // should never fail
pindex = pindex->pprev;
}
}
And what it should be:
for (unsigned int i = 1; i <= nPastBlocks; i++) {
arith_uint256 bnTarget = arith_uint256().SetCompact(pindex->nBits);
bnPastTargetAvg += bnTarget/nPastBlocks; // simple average
pindex = pindex->pprev;
}