Skip to content

Commit fa76b37

Browse files
author
MarcoFalke
committed
rpc: Round verificationprogress to exactly 1 for a recent tip
This requires a new lock annotation, but all relevant callers already held the lock.
1 parent faf6304 commit fa76b37

File tree

4 files changed

+23
-5
lines changed

4 files changed

+23
-5
lines changed

src/node/interfaces.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ class NodeImpl : public Node
326326
}
327327
double getVerificationProgress() override
328328
{
329-
return chainman().GuessVerificationProgress(WITH_LOCK(chainman().GetMutex(), return chainman().ActiveChain().Tip()));
329+
LOCK(chainman().GetMutex());
330+
return chainman().GuessVerificationProgress(chainman().ActiveTip());
330331
}
331332
bool isInitialBlockDownload() override
332333
{
@@ -409,6 +410,7 @@ class NodeImpl : public Node
409410
std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override
410411
{
411412
return MakeSignalHandler(::uiInterface.NotifyBlockTip_connect([fn, this](SynchronizationState sync_state, const CBlockIndex* block) {
413+
LOCK(chainman().GetMutex());
412414
fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()},
413415
chainman().GuessVerificationProgress(block));
414416
}));

src/validation.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5558,10 +5558,9 @@ bool Chainstate::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
55585558
return ret;
55595559
}
55605560

5561-
//! Guess how far we are in the verification process at the given block index
5562-
//! require cs_main if pindex has not been validated yet (because m_chain_tx_count might be unset)
55635561
double ChainstateManager::GuessVerificationProgress(const CBlockIndex* pindex) const
55645562
{
5563+
AssertLockHeld(GetMutex());
55655564
const ChainTxData& data{GetParams().TxData()};
55665565
if (pindex == nullptr) {
55675566
return 0.0;
@@ -5573,13 +5572,24 @@ double ChainstateManager::GuessVerificationProgress(const CBlockIndex* pindex) c
55735572
}
55745573

55755574
const int64_t nNow{TicksSinceEpoch<std::chrono::seconds>(NodeClock::now())};
5575+
const auto block_time{
5576+
(Assume(m_best_header) && std::abs(nNow - pindex->GetBlockTime()) <= Ticks<std::chrono::seconds>(2h) &&
5577+
Assume(m_best_header->nHeight >= pindex->nHeight)) ?
5578+
// When the header is known to be recent, switch to a height-based
5579+
// approach. This ensures the returned value is quantized when
5580+
// close to "1.0", because some users expect it to be. This also
5581+
// avoids relying too much on the exact miner-set timestamp, which
5582+
// may be off.
5583+
nNow - (m_best_header->nHeight - pindex->nHeight) * GetConsensus().nPowTargetSpacing :
5584+
pindex->GetBlockTime(),
5585+
};
55765586

55775587
double fTxTotal;
55785588

55795589
if (pindex->m_chain_tx_count <= data.tx_count) {
55805590
fTxTotal = data.tx_count + (nNow - data.nTime) * data.dTxRate;
55815591
} else {
5582-
fTxTotal = pindex->m_chain_tx_count + (nNow - pindex->GetBlockTime()) * data.dTxRate;
5592+
fTxTotal = pindex->m_chain_tx_count + (nNow - block_time) * data.dTxRate;
55835593
}
55845594

55855595
return std::min<double>(pindex->m_chain_tx_count / fTxTotal, 1.0);

src/validation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1147,7 +1147,7 @@ class ChainstateManager
11471147
bool IsInitialBlockDownload() const;
11481148

11491149
/** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */
1150-
double GuessVerificationProgress(const CBlockIndex* pindex) const;
1150+
double GuessVerificationProgress(const CBlockIndex* pindex) const EXCLUSIVE_LOCKS_REQUIRED(GetMutex());
11511151

11521152
/**
11531153
* Import blocks from an external file

test/functional/rpc_blockchain.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,13 @@ def _test_verificationprogress(self):
286286
future = 2 * 60 * 60
287287
self.nodes[0].setmocktime(self.nodes[0].getblockchaininfo()["time"] + future + 1)
288288
assert_greater_than(1, self.nodes[0].getblockchaininfo()["verificationprogress"])
289+
290+
self.log.info("Check that verificationprogress is exactly 1 for a recent block tip")
289291
self.nodes[0].setmocktime(self.nodes[0].getblockchaininfo()["time"] + future)
292+
assert_equal(1, self.nodes[0].getblockchaininfo()["verificationprogress"])
293+
294+
self.log.info("Check that verificationprogress is less than 1 as soon as a new header comes in")
295+
self.nodes[0].submitheader(self.generateblock(self.nodes[0], output="raw(55)", transactions=[], submit=False, sync_fun=self.no_op)["hex"])
290296
assert_greater_than(1, self.nodes[0].getblockchaininfo()["verificationprogress"])
291297

292298
def _test_y2106(self):

0 commit comments

Comments
 (0)