From 047aec1e0eafd0e5f9a80d841afd309730d8d4f8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 26 Jun 2017 16:16:08 -0700 Subject: [PATCH] Add block download progress to metrics UI --- src/gtest/test_metrics.cpp | 25 +++++++++++++++++++++++++ src/metrics.cpp | 35 ++++++++++++++++++++++++++++++++++- src/metrics.h | 3 +++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/gtest/test_metrics.cpp b/src/gtest/test_metrics.cpp index c199b323e..8e0aa9e02 100644 --- a/src/gtest/test_metrics.cpp +++ b/src/gtest/test_metrics.cpp @@ -92,3 +92,28 @@ TEST(Metrics, GetLocalSolPS) { SetMockTime(104); EXPECT_EQ(1, GetLocalSolPS()); } + +TEST(Metrics, EstimateNetHeightInner) { + // Ensure that the (rounded) current height is returned if the tip is current + SetMockTime(15000); + EXPECT_EQ(100, EstimateNetHeightInner(100, 14250, 50, 7500, 150)); + SetMockTime(15150); + EXPECT_EQ(100, EstimateNetHeightInner(101, 14400, 50, 7500, 150)); + + // Ensure that correct estimates are returned if the tip is in the past + SetMockTime(15300); // Tip is 2 blocks behind + EXPECT_EQ(100, EstimateNetHeightInner(100, 14250, 50, 7500, 150)); + SetMockTime(15900); // Tip is 6 blocks behind + EXPECT_EQ(110, EstimateNetHeightInner(100, 14250, 50, 7500, 150)); + + // More complex calculations: + SetMockTime(20000); + // - Checkpoint spacing: 200 + // -> Average spacing: 175 + // -> estimated height: 127 -> 130 + EXPECT_EQ(130, EstimateNetHeightInner(100, 14250, 50, 5250, 150)); + // - Checkpoint spacing: 50 + // -> Average spacing: 100 + // -> estimated height: 153 -> 150 + EXPECT_EQ(150, EstimateNetHeightInner(100, 14250, 50, 12000, 150)); +} diff --git a/src/metrics.cpp b/src/metrics.cpp index af8052049..b10e94630 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -5,6 +5,7 @@ #include "metrics.h" #include "chainparams.h" +#include "checkpoints.h" #include "main.h" #include "ui_interface.h" #include "util.h" @@ -103,6 +104,30 @@ double GetLocalSolPS() return miningTimer.rate(solutionTargetChecks); } +int EstimateNetHeightInner(int height, int64_t tipmediantime, + int heightLastCheckpoint, int64_t timeLastCheckpoint, + int64_t targetSpacing) +{ + // We average the target spacing with the observed spacing to the last + // checkpoint, and use that to estimate the current network height. + int medianHeight = height - CBlockIndex::nMedianTimeSpan / 2; + double checkpointSpacing = (double (tipmediantime - timeLastCheckpoint)) / (medianHeight - heightLastCheckpoint); + double averageSpacing = (targetSpacing + checkpointSpacing) / 2; + int netheight = medianHeight + ((GetTime() - tipmediantime) / averageSpacing); + // Round to nearest ten to reduce noise + return ((netheight + 5) / 10) * 10; +} + +int EstimateNetHeight(int height, int64_t tipmediantime, CChainParams chainParams) +{ + auto checkpointData = chainParams.Checkpoints(); + return EstimateNetHeightInner( + height, tipmediantime, + Checkpoints::GetTotalBlocksEstimate(checkpointData), + checkpointData.nTimeLastCheckpoint, + chainParams.GetConsensus().nPowTargetSpacing); +} + void TriggerRefresh() { *nNextRefresh = GetTime(); @@ -169,17 +194,25 @@ int printStats(bool mining) int lines = 4; int height; + int64_t tipmediantime; size_t connections; int64_t netsolps; { LOCK2(cs_main, cs_vNodes); height = chainActive.Height(); + tipmediantime = chainActive.Tip()->GetMedianTimePast(); connections = vNodes.size(); netsolps = GetNetworkHashPS(120, -1); } auto localsolps = GetLocalSolPS(); - std::cout << " " << _("Block height") << " | " << height << std::endl; + if (IsInitialBlockDownload()) { + int netheight = EstimateNetHeight(height, tipmediantime, Params()); + int downloadPercent = height * 100 / netheight; + std::cout << " " << _("Downloading blocks") << " | " << height << " / ~" << netheight << " (" << downloadPercent << "%)" << std::endl; + } else { + std::cout << " " << _("Block height") << " | " << height << std::endl; + } std::cout << " " << _("Connections") << " | " << connections << std::endl; std::cout << " " << _("Network solution rate") << " | " << netsolps << " Sol/s" << std::endl; if (mining && miningTimer.running()) { diff --git a/src/metrics.h b/src/metrics.h index 701306a4a..7f7efdea6 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -63,6 +63,9 @@ void TrackMinedBlock(uint256 hash); void MarkStartTime(); double GetLocalSolPS(); +int EstimateNetHeightInner(int height, int64_t tipmediantime, + int heightLastCheckpoint, int64_t timeLastCheckpoint, + int64_t targetSpacing); void TriggerRefresh();