Skip to content

Commit

Permalink
Fix progress reporting issue
Browse files Browse the repository at this point in the history
Reimplementation of Blockstream/liquid#6
  • Loading branch information
stevenroose committed Mar 20, 2019
1 parent e358d8f commit 54ec706
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 27 deletions.
6 changes: 3 additions & 3 deletions src/interfaces/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class NodeImpl : public Node
LOCK(::cs_main);
tip = ::chainActive.Tip();
}
return GuessVerificationProgress(Params().TxData(), tip);
return GuessVerificationProgress(tip, Params().GetConsensus().nPowTargetSpacing);
}
bool isInitialBlockDownload() override { return IsInitialBlockDownload(); }
bool getReindex() override { return ::fReindex; }
Expand Down Expand Up @@ -266,15 +266,15 @@ class NodeImpl : public Node
{
return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](bool initial_download, const CBlockIndex* block) {
fn(initial_download, block->nHeight, block->GetBlockTime(),
GuessVerificationProgress(Params().TxData(), block));
GuessVerificationProgress(block, Params().GetConsensus().nPowTargetSpacing));
}));
}
std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override
{
return MakeHandler(
::uiInterface.NotifyHeaderTip_connect([fn](bool initial_download, const CBlockIndex* block) {
fn(initial_download, block->nHeight, block->GetBlockTime(),
GuessVerificationProgress(Params().TxData(), block));
GuessVerificationProgress(block, Params().GetConsensus().nPowTargetSpacing));
}));
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1292,7 +1292,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
obj.pushKV("difficulty", (double)GetDifficulty(chainActive.Tip()));
}
obj.pushKV("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast());
obj.pushKV("verificationprogress", GuessVerificationProgress(chainparams.TxData(), chainActive.Tip()));
obj.pushKV("verificationprogress", GuessVerificationProgress(chainActive.Tip(), chainparams.GetConsensus().nPowTargetSpacing));
obj.pushKV("initialblockdownload", IsInitialBlockDownload());
if (!g_signed_blocks) {
obj.pushKV("chainwork", chainActive.Tip()->nChainWork.GetHex());
Expand Down
34 changes: 17 additions & 17 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2394,7 +2394,8 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion,
log(pindexNew->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx,
FormatISO8601DateTime(pindexNew->GetBlockTime()),
GuessVerificationProgress(chainParams.TxData(), pindexNew), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
GuessVerificationProgress(pindexNew, chainParams.GetConsensus().nPowTargetSpacing),
pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
if (!warningMessages.empty())
LogPrintf(" warning='%s'", warningMessages); /* Continued */
LogPrintf("\n");
Expand Down Expand Up @@ -4203,10 +4204,10 @@ bool LoadChainTip(const CChainParams& chainparams)

g_chainstate.PruneBlockIndexCandidates();

LogPrintf("Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
LogPrintf("Loaded best chain: hashBestChain=%s height=%d date=%s progress=%.3f\n",
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(),
FormatISO8601DateTime(chainActive.Tip()->GetBlockTime()),
GuessVerificationProgress(chainparams.TxData(), chainActive.Tip()));
GuessVerificationProgress(chainActive.Tip(), chainparams.GetConsensus().nPowTargetSpacing));
return true;
}

Expand Down Expand Up @@ -5067,23 +5068,22 @@ bool DumpMempool(void)
return true;
}

//! Guess how far we are in the verification process at the given block index
//! require cs_main if pindex has not been validated yet (because nChainTx might be unset)
double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pindex) {
if (pindex == nullptr)
//! Guess how far we are in the verification process at the given block index.
//! Since we have signed fixed-interval blocks, estimating progress is a very easy.
//! We can extrapolate the last block time to the current time to estimate how many more blocks
//! we expect.
double GuessVerificationProgress(const CBlockIndex* pindex, int64_t blockInterval) {
if (pindex == NULL || pindex->nHeight < 1) {
return 0.0;

int64_t nNow = time(nullptr);

double fTxTotal;

if (pindex->nChainTx <= data.nTxCount) {
fTxTotal = data.nTxCount + (nNow - data.nTime) * data.dTxRate;
} else {
fTxTotal = pindex->nChainTx + (nNow - pindex->GetBlockTime()) * data.dTxRate;
}

return pindex->nChainTx / fTxTotal;
int64_t nNow = GetTime();
int64_t moreBlocksExpected = (nNow - pindex->GetBlockTime()) / blockInterval;
double progress = (pindex->nHeight + 0.0) / (pindex->nHeight + moreBlocksExpected);
// Round to 3 digits to avoid 0.999999 when finished.
progress = ceil(progress * 1000.0) / 1000.0;
// Avoid higher than one if last block is newer than current time.
return std::min(1.0, progress);
}

class CMainCleanup
Expand Down
2 changes: 1 addition & 1 deletion src/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams,
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);

/** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */
double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex* pindex);
double GuessVerificationProgress(const CBlockIndex* pindex, int64_t blockInterval);

/** Calculate the amount of disk space the block & undo files currently use */
uint64_t CalculateCurrentUsage();
Expand Down
10 changes: 5 additions & 5 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1707,12 +1707,12 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
double progress_end;
{
LOCK(cs_main);
progress_begin = GuessVerificationProgress(chainParams.TxData(), pindex);
progress_begin = GuessVerificationProgress(pindex, chainParams.GetConsensus().nPowTargetSpacing);
if (pindexStop == nullptr) {
tip = chainActive.Tip();
progress_end = GuessVerificationProgress(chainParams.TxData(), tip);
progress_end = GuessVerificationProgress(tip, chainParams.GetConsensus().nPowTargetSpacing);
} else {
progress_end = GuessVerificationProgress(chainParams.TxData(), pindexStop);
progress_end = GuessVerificationProgress(pindexStop, chainParams.GetConsensus().nPowTargetSpacing);
}
}
double progress_current = progress_begin;
Expand Down Expand Up @@ -1747,11 +1747,11 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
{
LOCK(cs_main);
pindex = chainActive.Next(pindex);
progress_current = GuessVerificationProgress(chainParams.TxData(), pindex);
progress_current = GuessVerificationProgress(pindex, chainParams.GetConsensus().nPowTargetSpacing);
if (pindexStop == nullptr && tip != chainActive.Tip()) {
tip = chainActive.Tip();
// in case the tip has changed, update progress max
progress_end = GuessVerificationProgress(chainParams.TxData(), tip);
progress_end = GuessVerificationProgress(tip, chainParams.GetConsensus().nPowTargetSpacing);
}
}
}
Expand Down
59 changes: 59 additions & 0 deletions test/functional/progress.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2016 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

#
# Test progress code
#

import time

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
Decimal,
)

def assert_close(f1, f2):
assert(abs(Decimal(f1)-f2) < 0.1)

class ProgressTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
self.extra_args = [["-debug", "-con_npowtargetspacing=1", "-maxtimeadjustment=0"]] * self.num_nodes

def setup_network(self):
self.setup_nodes()
self.is_network_split = True
self.starttime = int(time.time())

def setmocktime(self, ntime):
for node in self.nodes:
node.setmocktime(self.starttime + ntime)

def run_test(self):
node1 = self.nodes[0]
node2 = self.nodes[1]
self.setmocktime(0)

blocks = []
for i in range(10):
self.setmocktime(i)
blocks.extend(node1.generate(1))

self.setmocktime(19)
assert_close(0.5, node1.getblockchaininfo()["verificationprogress"])

assert(node2.getblockchaininfo()["initialblockdownload"])

self.setmocktime(10)
for i in range(10):
node2.submitblock(node1.getblock(blocks[i], False))
progress = node2.getblockchaininfo()["verificationprogress"]
assert_close(i/10.0, progress)

assert(not node2.getblockchaininfo()["initialblockdownload"])

if __name__ == '__main__':
ProgressTest().main()
1 change: 1 addition & 0 deletions test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
'feature_default_asset_name.py',
'feature_assetsdir.py',
'feature_initial_reissuance_token.py',
'progress.py',
# Longest test should go first, to favor running tests in parallel
'feature_fee_estimation.py',
'wallet_hd.py',
Expand Down

0 comments on commit 54ec706

Please sign in to comment.