Fix progress reporting issue

Reimplementation of https://github.com/Blockstream/liquid/pull/6
This commit is contained in:
Steven Roose 2019-03-20 15:45:18 +00:00
parent e9f6e82bbf
commit 5b8c79ac9d
No known key found for this signature in database
GPG key ID: 7FC91380BB4CE800
7 changed files with 87 additions and 27 deletions

View file

@ -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; }
@ -266,7 +266,7 @@ 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
@ -274,7 +274,7 @@ class NodeImpl : public Node
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));
}));
}
};

View file

@ -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());

View file

@ -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");
@ -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;
}
@ -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

View file

@ -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();

View file

@ -1708,12 +1708,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;
@ -1748,11 +1748,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);
}
}
}

View file

@ -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()

View file

@ -73,6 +73,7 @@ BASE_SCRIPTS = [
'feature_default_asset_name.py',
'feature_assetsdir.py',
'feature_initial_reissuance_token.py',
'feature_progress.py',
# Longest test should go first, to favor running tests in parallel
'wallet_hd.py',
'wallet_backup.py',