diff --git a/backend/src/api/difficulty-adjustment.ts b/backend/src/api/difficulty-adjustment.ts index 1f85fdb80..37a0e7a8d 100644 --- a/backend/src/api/difficulty-adjustment.ts +++ b/backend/src/api/difficulty-adjustment.ts @@ -6,33 +6,37 @@ class DifficultyAdjustmentApi { constructor() { } public getDifficultyAdjustment(): IDifficultyAdjustment { + const ESTIMATE_LAG_BLOCKS = 146; // For first 7.2% of epoch, don't estimate. + const EPOCH_BLOCK_LENGTH = 2016; + const DATime = blocks.getLastDifficultyAdjustmentTime(); const previousRetarget = blocks.getPreviousDifficultyRetarget(); const blockHeight = blocks.getCurrentBlockHeight(); const blocksCache = blocks.getBlocks(); const latestBlock = blocksCache[blocksCache.length - 1]; - const now = new Date().getTime() / 1000; - const diff = now - DATime; - const blocksInEpoch = blockHeight % 2016; - const progressPercent = (blocksInEpoch >= 0) ? blocksInEpoch / 2016 * 100 : 100; - const remainingBlocks = 2016 - blocksInEpoch; - const nextRetargetHeight = blockHeight + remainingBlocks; + const nowSeconds = Math.floor(new Date().getTime() / 1000); + const diffSeconds = nowSeconds - DATime; + const blocksInEpoch = (blockHeight >= 0) ? blockHeight % EPOCH_BLOCK_LENGTH : 0; + const progressPercent = (blockHeight >= 0) ? blocksInEpoch / EPOCH_BLOCK_LENGTH * 100 : 100; + const remainingBlocks = EPOCH_BLOCK_LENGTH - blocksInEpoch; + const nextRetargetHeight = (blockHeight >= 0) ? blockHeight + remainingBlocks : 0; let difficultyChange = 0; - if (remainingBlocks < 1870) { - if (blocksInEpoch > 0) { - difficultyChange = (600 / (diff / blocksInEpoch) - 1) * 100; - } + // Only calculate the estimate once we have 7.2% of blocks in current epoch + if (blocksInEpoch >= ESTIMATE_LAG_BLOCKS) { + difficultyChange = (600 / (diffSeconds / blocksInEpoch) - 1) * 100; + // Max increase is x4 (+300%) if (difficultyChange > 300) { difficultyChange = 300; } + // Max decrease is /4 (-75%) if (difficultyChange < -75) { difficultyChange = -75; } } - let timeAvgMins = blocksInEpoch && blocksInEpoch > 146 ? diff / blocksInEpoch / 60 : 10; + let timeAvgMins = blocksInEpoch >= ESTIMATE_LAG_BLOCKS ? diffSeconds / blocksInEpoch / 60 : 10; // Testnet difficulty is set to 1 after 20 minutes of no blocks, // therefore the time between blocks will always be below 20 minutes (1200s). @@ -41,14 +45,14 @@ class DifficultyAdjustmentApi { if (timeAvgMins > 20) { timeAvgMins = 20; } - if (now - latestBlock.timestamp + timeAvgMins * 60 > 1200) { - timeOffset = -Math.min(now - latestBlock.timestamp, 1200) * 1000; + if (nowSeconds - latestBlock.timestamp + timeAvgMins * 60 > 1200) { + timeOffset = -Math.min(nowSeconds - latestBlock.timestamp, 1200) * 1000; } } - const timeAvg = timeAvgMins * 60 * 1000 ; - const remainingTime = (remainingBlocks * timeAvg) + (now * 1000); - const estimatedRetargetDate = remainingTime + now; + const timeAvg = Math.floor(timeAvgMins * 60 * 1000); + const remainingTime = remainingBlocks * timeAvg; + const estimatedRetargetDate = remainingTime + nowSeconds * 1000; return { progressPercent, diff --git a/frontend/src/app/components/difficulty/difficulty.component.html b/frontend/src/app/components/difficulty/difficulty.component.html index 3684b8de4..e030f74fa 100644 --- a/frontend/src/app/components/difficulty/difficulty.component.html +++ b/frontend/src/app/components/difficulty/difficulty.component.html @@ -10,7 +10,7 @@ {{ i }} blocks {{ i }} block -
+
Estimate
diff --git a/frontend/src/app/components/difficulty/difficulty.component.ts b/frontend/src/app/components/difficulty/difficulty.component.ts index 5d969bf1e..76a996acc 100644 --- a/frontend/src/app/components/difficulty/difficulty.component.ts +++ b/frontend/src/app/components/difficulty/difficulty.component.ts @@ -11,7 +11,7 @@ interface EpochProgress { newDifficultyHeight: number; colorAdjustments: string; colorPreviousAdjustments: string; - remainingTime: number; + estimatedRetargetDate: number; previousRetarget: number; blocksUntilHalving: number; timeUntilHalving: number; @@ -74,7 +74,7 @@ export class DifficultyComponent implements OnInit { colorAdjustments, colorPreviousAdjustments, newDifficultyHeight: da.nextRetargetHeight, - remainingTime: da.remainingTime, + estimatedRetargetDate: da.estimatedRetargetDate, previousRetarget: da.previousRetarget, blocksUntilHalving, timeUntilHalving,