Fix Difficulty Retargeting
This commit is contained in:
parent
2bc297d93b
commit
2caeac559a
@ -14,6 +14,7 @@ const Logger = require('blgr');
|
||||
const {Lock} = require('bmutex');
|
||||
const LRU = require('blru');
|
||||
const {BufferMap} = require('buffer-map');
|
||||
const BN = require('bcrypto/lib/bn.js');
|
||||
const Network = require('../protocol/network');
|
||||
const ChainDB = require('./chaindb');
|
||||
const common = require('./common');
|
||||
@ -380,8 +381,7 @@ class Chain extends AsyncEmitter {
|
||||
// Ensure the POW is what we expect.
|
||||
const bits = await this.getTarget(block.time, prev);
|
||||
|
||||
// FLO Block 39511 on testnet fails this check for some reason, hardcode to allow until further research can be done.
|
||||
if (block.bits !== bits && block.height >= 39512) {
|
||||
if (block.bits !== bits) {
|
||||
throw new VerifyError(block,
|
||||
'invalid',
|
||||
'bad-diffbits',
|
||||
@ -2198,35 +2198,37 @@ class Chain extends AsyncEmitter {
|
||||
return pow.bits;
|
||||
}
|
||||
|
||||
let retargetInterval, targetSpacing, averagingInterval;
|
||||
let retargetInterval, averagingInterval, targetTimespan;
|
||||
|
||||
if (prev.height < pow.blockHeight_version2){
|
||||
let targetSpacing = pow.targetSpacing
|
||||
|
||||
retargetInterval = pow.retargetInterval_version1;
|
||||
targetSpacing = pow.targetSpacing_version1;
|
||||
averagingInterval = pow.averagingInterval_version1;
|
||||
if ((prev.height + 1) < pow.blockHeight_Version2){
|
||||
|
||||
} else if (prev.height >= pow.blockHeight_version2 && prev.height < pow.blockHeight_version3){
|
||||
retargetInterval = pow.retargetInterval_Version1;
|
||||
averagingInterval = pow.averagingInterval_Version1;
|
||||
targetTimespan = pow.targetTimespan_Version1;
|
||||
|
||||
} else if ((prev.height + 1) < pow.blockHeight_Version3){
|
||||
|
||||
retargetInterval = pow.retargetInterval_version2;
|
||||
targetSpacing = pow.targetSpacing_version2;
|
||||
averagingInterval = pow.averagingInterval_version2;
|
||||
retargetInterval = pow.retargetInterval_Version2;
|
||||
averagingInterval = pow.averagingInterval_Version2;
|
||||
targetTimespan = pow.targetTimespan_Version2 * targetSpacing;
|
||||
|
||||
} else if (prev.height >= pow.blockHeight_version3) {
|
||||
} else {
|
||||
|
||||
retargetInterval = pow.retargetInterval_version3;
|
||||
targetSpacing = pow.targetSpacing_version3;
|
||||
averagingInterval = pow.averagingInterval_version3;
|
||||
retargetInterval = pow.retargetInterval_Version3;
|
||||
averagingInterval = pow.averagingInterval_Version3;
|
||||
targetTimespan = pow.targetTimespan_Version3 * targetSpacing;
|
||||
|
||||
}
|
||||
|
||||
// Do not retarget
|
||||
if ((prev.height + 1) % retargetInterval !== 0) {
|
||||
if (pow.targetReset) {
|
||||
// Special behavior for testnet:
|
||||
if (time > prev.time + targetSpacing * 2)
|
||||
// Special behavior for testnet
|
||||
if (time > prev.time + (targetTimespan * 2)) {
|
||||
return pow.bits;
|
||||
|
||||
}
|
||||
while (prev.height !== 0
|
||||
&& prev.height % retargetInterval !== 0
|
||||
&& prev.bits === pow.bits) {
|
||||
@ -2243,21 +2245,19 @@ class Chain extends AsyncEmitter {
|
||||
return prev.bits;
|
||||
}
|
||||
|
||||
// Back 6 block
|
||||
var back = averagingInterval - 1;
|
||||
// Back 6 block
|
||||
var back = averagingInterval - 1;
|
||||
|
||||
if (prev.height + 1 !== averagingInterval)
|
||||
back = averagingInterval;
|
||||
|
||||
let first = prev;
|
||||
for (let i = 0; i < back; i++){
|
||||
if (first)
|
||||
first = await this.getPrevious(first)
|
||||
}
|
||||
|
||||
|
||||
if (prev.height + 1 !== averagingInterval)
|
||||
back = averagingInterval;
|
||||
|
||||
|
||||
let first = prev;
|
||||
for (let i = 0; i < back; i++){
|
||||
if (first)
|
||||
first = await this.getPrevious(first)
|
||||
}
|
||||
|
||||
assert(first);
|
||||
assert(first);
|
||||
|
||||
return this.retarget(prev, first);
|
||||
}
|
||||
@ -2273,75 +2273,69 @@ class Chain extends AsyncEmitter {
|
||||
retarget(prev, first) {
|
||||
const pow = this.network.pow;
|
||||
|
||||
let height = prev.height;
|
||||
if (pow.noRetargeting)
|
||||
return prev.bits;
|
||||
|
||||
let height = prev.height + 1;
|
||||
|
||||
let targetTimespan, averagingIntervalTimespan, targetSpacing, adjustUp, adjustDown;
|
||||
|
||||
if (height < pow.blockHeight_version2){
|
||||
targetSpacing = pow.targetSpacing
|
||||
|
||||
targetTimespan = pow.targetTimespan_version1;
|
||||
averagingIntervalTimespan = pow.averagingIntervalTimespan_version1;
|
||||
targetSpacing = pow.targetSpacing_version1;
|
||||
adjustUp = pow.adjustUp_version1;
|
||||
adjustDown = pow.adjustDown_version1;
|
||||
if (height < pow.blockHeight_Version2){
|
||||
|
||||
} else if (height >= pow.blockHeight_version2 && height < pow.blockHeight_version3){
|
||||
targetTimespan = pow.targetTimespan_Version1;
|
||||
averagingIntervalTimespan = pow.averagingIntervalTimespan_Version1;
|
||||
adjustUp = pow.adjustUp_Version1;
|
||||
adjustDown = pow.adjustDown_Version1;
|
||||
|
||||
targetTimespan = pow.targetTimespan_version2;
|
||||
averagingIntervalTimespan = pow.averagingIntervalTimespan_version2;
|
||||
targetSpacing = pow.targetSpacing_version2;
|
||||
adjustUp = pow.adjustUp_version2;
|
||||
adjustDown = pow.adjustDown_version2;
|
||||
} else if (height < pow.blockHeight_Version3){
|
||||
|
||||
} else if (height >= pow.blockHeight_version3) {
|
||||
|
||||
targetTimespan = pow.targetTimespan_version3;
|
||||
averagingIntervalTimespan = pow.averagingIntervalTimespan_version3;
|
||||
targetSpacing = pow.targetSpacing_version3;
|
||||
adjustUp = pow.adjustUp_version3;
|
||||
adjustDown = pow.adjustDown_version3;
|
||||
targetTimespan = pow.targetTimespan_Version2;
|
||||
averagingIntervalTimespan = pow.averagingIntervalTimespan_Version2;
|
||||
adjustUp = pow.adjustUp_Version2;
|
||||
adjustDown = pow.adjustDown_Version2;
|
||||
|
||||
} else {
|
||||
// Difficulty NOT handled?!?
|
||||
|
||||
targetTimespan = pow.targetTimespan_Version3;
|
||||
averagingIntervalTimespan = pow.averagingIntervalTimespan_Version3;
|
||||
adjustUp = pow.adjustUp_Version3;
|
||||
adjustDown = pow.adjustDown_Version3;
|
||||
|
||||
}
|
||||
|
||||
if (pow.noRetargeting)
|
||||
return prev.bits;
|
||||
averagingIntervalTimespan = averagingIntervalTimespan * targetSpacing
|
||||
|
||||
let actualTimespan = prev.time - first.time;
|
||||
|
||||
// console.log("Actual Timespan: " + actualTimespan);
|
||||
|
||||
let minActualTimespan = Math.floor(averagingIntervalTimespan * (100 - adjustUp) / 100)
|
||||
let maxActualTimespan = Math.floor(averagingIntervalTimespan * (100 + adjustDown) / 100)
|
||||
|
||||
// console.log("minActualTimespan: " + minActualTimespan);
|
||||
// console.log("maxActualTimespan: " + maxActualTimespan);
|
||||
|
||||
if (actualTimespan < minActualTimespan)
|
||||
actualTimespan = minActualTimespan;
|
||||
|
||||
// console.log("New Actual Timespan: " + actualTimespan)
|
||||
|
||||
if (actualTimespan > maxActualTimespan)
|
||||
actualTimespan = maxActualTimespan;
|
||||
|
||||
// console.log("New Actual Timespan: " + actualTimespan)
|
||||
|
||||
// Retarget
|
||||
let target = consensus.fromCompact(prev.bits);
|
||||
|
||||
// console.log("Target: " + target)
|
||||
// FLO: intermediate uint256 can overflow by 1 bit
|
||||
let fShift = (consensus.toCompact(target) > pow.bits - 1)
|
||||
|
||||
if (fShift)
|
||||
target.ishl(new BN(1))
|
||||
|
||||
target.imuln(actualTimespan);
|
||||
// console.log("imuln: " + target)
|
||||
target.idivn(targetTimespan);
|
||||
// console.log("idivn: " + target)
|
||||
|
||||
if (target.gt(pow.limit))
|
||||
return pow.bits;
|
||||
if (fShift)
|
||||
target.ishr(new BN(1))
|
||||
|
||||
// console.log("gt: " + target)
|
||||
if (consensus.toCompact(target) > pow.bits){
|
||||
return pow.bits;
|
||||
}
|
||||
|
||||
return consensus.toCompact(target);
|
||||
}
|
||||
|
||||
@ -222,14 +222,6 @@ main.pow = {
|
||||
'hex'
|
||||
),
|
||||
|
||||
/**
|
||||
* Desired retarget period in seconds.
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
targetTimespan: 6 * 40,
|
||||
|
||||
/**
|
||||
* Average block time.
|
||||
* @const {Number}
|
||||
@ -238,13 +230,25 @@ main.pow = {
|
||||
|
||||
targetSpacing: 40,
|
||||
|
||||
/**
|
||||
* Desired retarget period in seconds.
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
targetTimespan_Version1: 60 * 60,
|
||||
targetTimespan_Version2: 15 * 40,
|
||||
targetTimespan_Version3: 6 * 40,
|
||||
|
||||
/**
|
||||
* Retarget interval in blocks.
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
retargetInterval: 1,
|
||||
retargetInterval_Version1: (60 * 60) / 40,
|
||||
retargetInterval_Version2: 15,
|
||||
retargetInterval_Version3: 1,
|
||||
|
||||
/**
|
||||
* Average retarget interval in blocks.
|
||||
@ -252,7 +256,9 @@ main.pow = {
|
||||
* @default
|
||||
*/
|
||||
|
||||
averagingInterval: 6,
|
||||
averagingInterval_Version1: (60 * 60) / 40,
|
||||
averagingInterval_Version2: 15,
|
||||
averagingInterval_Version3: 6,
|
||||
|
||||
/**
|
||||
* Average retarget interval in blocks.
|
||||
@ -260,7 +266,9 @@ main.pow = {
|
||||
* @default
|
||||
*/
|
||||
|
||||
averagingIntervalTimespan: 6 * 40,
|
||||
averagingIntervalTimespan_Version1: (60 * 60) / 40,
|
||||
averagingIntervalTimespan_Version2: 15,
|
||||
averagingIntervalTimespan_Version3: 6,
|
||||
|
||||
/**
|
||||
* Adjust Target Timespan Max.
|
||||
@ -268,7 +276,9 @@ main.pow = {
|
||||
* @default
|
||||
*/
|
||||
|
||||
adjustUp: 2,
|
||||
adjustUp_Version1: 75,
|
||||
adjustUp_Version2: 75,
|
||||
adjustUp_Version3: 2,
|
||||
|
||||
/**
|
||||
* Adjust Target Timespan Min.
|
||||
@ -276,31 +286,17 @@ main.pow = {
|
||||
* @default
|
||||
*/
|
||||
|
||||
adjustDown: 3,
|
||||
adjustDown_Version1: 300,
|
||||
adjustDown_Version2: 300,
|
||||
adjustDown_Version3: 3,
|
||||
|
||||
targetTimespan_version1: 60 * 60,
|
||||
targetSpacing_version1: 40,
|
||||
retargetInterval_version1: (60 * 60) / 40,
|
||||
averagingInterval_version1: (60 * 60) / 40,
|
||||
averagingIntervalTimespan_version1: ((60 * 60) / 40) * 40,
|
||||
adjustUp_version1: 75,
|
||||
adjustDown_version1: 300,
|
||||
blockHeight_version2: 208440,
|
||||
targetTimespan_version2: 15 * 40,
|
||||
targetSpacing_version2: 40,
|
||||
retargetInterval_version2: 15,
|
||||
averagingInterval_version2: 15,
|
||||
averagingIntervalTimespan_version2: 15 * 40,
|
||||
adjustUp_version2: 75,
|
||||
adjustDown_version2: 300,
|
||||
blockHeight_version3: 426000,
|
||||
targetTimespan_version3: 6 * 40,
|
||||
targetSpacing_version3: 40,
|
||||
retargetInterval_version3: 1,
|
||||
averagingInterval_version3: 6,
|
||||
averagingIntervalTimespan_version3: 6 * 40,
|
||||
adjustUp_version3: 2,
|
||||
adjustDown_version3: 3,
|
||||
/**
|
||||
* Block Heights that each difficulty algorithm should be used
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
blockHeight_Version2: 208440,
|
||||
blockHeight_Version3: 426000,
|
||||
|
||||
/**
|
||||
* Whether to reset target if a block
|
||||
@ -622,32 +618,79 @@ testnet.pow = {
|
||||
),
|
||||
bits: 504365055,
|
||||
chainwork: new BN(
|
||||
'000000000000000000000000000000000000000000000000000000083540886d',
|
||||
'0000000000000000000000000000000000000000000000000000003dd47d3172',
|
||||
'hex'
|
||||
),
|
||||
targetTimespan_version1: 60 * 60,
|
||||
targetSpacing_version1: 40,
|
||||
retargetInterval_version1: (60 * 60) / 40,
|
||||
averagingInterval_version1: (60 * 60) / 40,
|
||||
averagingIntervalTimespan_version1: ((60 * 60) / 40) * 40,
|
||||
adjustUp_version1: 75,
|
||||
adjustDown_version1: 300,
|
||||
blockHeight_version2: 50000,
|
||||
targetTimespan_version2: 15 * 40,
|
||||
targetSpacing_version2: 40,
|
||||
retargetInterval_version2: 15,
|
||||
averagingInterval_version2: 15,
|
||||
averagingIntervalTimespan_version2: 15 * 40,
|
||||
adjustUp_version2: 75,
|
||||
adjustDown_version2: 300,
|
||||
blockHeight_version3: 60000,
|
||||
targetTimespan_version3: 6 * 40,
|
||||
targetSpacing_version3: 40,
|
||||
retargetInterval_version3: 1,
|
||||
averagingInterval_version3: 6,
|
||||
averagingIntervalTimespan_version3: 6 * 40,
|
||||
adjustUp_version3: 2,
|
||||
adjustDown_version3: 3,
|
||||
targetSpacing: 40,
|
||||
|
||||
/**
|
||||
* Desired retarget period in seconds.
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
targetTimespan_Version1: 60 * 60,
|
||||
targetTimespan_Version2: 15 * 40,
|
||||
targetTimespan_Version3: 6 * 40,
|
||||
|
||||
/**
|
||||
* Retarget interval in blocks.
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
retargetInterval_Version1: (60 * 60) / 40,
|
||||
retargetInterval_Version2: 15,
|
||||
retargetInterval_Version3: 1,
|
||||
|
||||
/**
|
||||
* Average retarget interval in blocks.
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
averagingInterval_Version1: (60 * 60) / 40,
|
||||
averagingInterval_Version2: 15,
|
||||
averagingInterval_Version3: 6,
|
||||
|
||||
/**
|
||||
* Average retarget interval in blocks.
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
averagingIntervalTimespan_Version1: (60 * 60) / 40,
|
||||
averagingIntervalTimespan_Version2: 15,
|
||||
averagingIntervalTimespan_Version3: 6,
|
||||
|
||||
/**
|
||||
* Adjust Target Timespan Max.
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
adjustUp_Version1: 75,
|
||||
adjustUp_Version2: 75,
|
||||
adjustUp_Version3: 2,
|
||||
|
||||
/**
|
||||
* Adjust Target Timespan Min.
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
adjustDown_Version1: 300,
|
||||
adjustDown_Version2: 300,
|
||||
adjustDown_Version3: 3,
|
||||
|
||||
/**
|
||||
* Block Heights that each difficulty algorithm should be used
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
blockHeight_Version2: 50000,
|
||||
blockHeight_Version3: 60000,
|
||||
|
||||
targetReset: true,
|
||||
noRetargeting: false
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user