Page MenuHomePhabricator

Implement weighted-time difficulty adjustment algorithm

Authored by deadalnix on Oct 22 2017, 15:20.


Group Reviewers
Restricted Owners Package(Owns No Changed Paths)
Restricted Project

This weighted-time DAA uses a 144-block sliding window and applies two weights to the individual inter-block times before retargeting.

Difficulty weight
To correct for the difficulty at which the block was mined, its time is multiplied by the ratio of its target to the final block's target.

Recency weight
Each blocktime is weighted by its sequence within the window, starting at 1 with the oldest block.

Test Plan

make check
A testnet effort is planned.
Extensive simulations have been done and continue. The simulation's python implementation temporarily remains as comments to aid review.

Diff Detail

rABC Bitcoin ABC
Lint Passed
No Test Coverage
Build Status
Buildable 1029
Build 1029: arc lint + arc unit

Event Timeline

Owners added a reviewer: Restricted Owners Package.Oct 22 2017, 15:20
dgenr8 retitled this revision from Imlplement weighted-time difficulty adjustment algorithm to Implement weighted-time difficulty adjustment algorithm.Oct 22 2017, 16:08
dgenr8 edited the test plan for this revision. (Show Details)
dgenr8 edited the test plan for this revision. (Show Details)
dgenr8 edited the test plan for this revision. (Show Details)
kyuupichan added a subscriber: kyuupichan.
kyuupichan added inline comments.
200 ↗(On Diff #1600)

I don't think the division is good here - as it's integer division it doesn't have sufficient granularity. Do we not want ((time_i * target_i) / last_target).GetLow64() - that matches the Python.

The rest looks good to me.

This revision now requires changes to proceed.Oct 22 2017, 21:51
200 ↗(On Diff #1600)

On regtest there is only 1 bit of room in the targets. So how about:

const uint32 DIFF_WEIGHT_PRECISION = 1000000;
last_target /= DIFF_WEIGHT_PRECISION; // outside the loop

uint32_t adj_time_i = time_i * ((target_i / DIFF_WEIGHT_PRECISION) / last_target).GetLow64();

200 ↗(On Diff #1600)

Looks good except we need a temporary rather than updating last_target. Will do.

200 ↗(On Diff #1600)


uint32_t adj_time_i = ((time_i * (target_i / DIFF_WEIGHT_PRECISION)) / last_target).GetLow64();

dgenr8 edited edge metadata.

Use 6-digit precision for 256-bit ratio

dgenr8 edited the summary of this revision. (Show Details)
Mengerian added inline comments.
203 ↗(On Diff #1602)

I notice that it divides by last_target inside the loop, then multiplies the result by last_target outside the loop.

Seems like the calculations could be done more efficiently removing the division inside the loop (and the subsequent multiplication outside)

203 ↗(On Diff #1602)

Great catch. This will also remove the need for fixed precision, we'll just need to accumulate in a 256-bit var.

deadalnix abandoned this revision.
deadalnix added a reviewer: dgenr8.