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));
+}
#include "metrics.h"
#include "chainparams.h"
+#include "checkpoints.h"
#include "main.h"
#include "ui_interface.h"
#include "util.h"
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();
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()) {