Skip to content

Commit 96b8025

Browse files
committed
Merge pull request #7112
9af5f9c Move uiInterface.NotifyBlockTip signal above the core/wallet signal - This will keep getbestblockhash more in sync with blocknotify callbacks (Jonas Schnelli) 4082e46 [Qt] call GuessVerificationProgress synchronous during core signal, pass double over UI signal (Jonas Schnelli) 947d20b [Qt] reduce cs_main in getVerificationProgress() (Jonas Schnelli) e6d50fc [Qt] update block tip (height and date) without locking cs_main, update always (each block) (Jonas Schnelli) 012fc91 NotifyBlockTip signal: switch from hash (uint256) to CBlockIndex* - also adds a boolean for indication if the tip update was happening during initial sync - emit notification also during initial sync (Jonas Schnelli)
2 parents a775182 + 9af5f9c commit 96b8025

File tree

10 files changed

+83
-80
lines changed

10 files changed

+83
-80
lines changed

src/init.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,11 +515,14 @@ std::string LicenseInfo()
515515
"\n";
516516
}
517517

518-
static void BlockNotifyCallback(const uint256& hashNewTip)
518+
static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex)
519519
{
520+
if (initialSync || !pBlockIndex)
521+
return;
522+
520523
std::string strCmd = GetArg("-blocknotify", "");
521524

522-
boost::replace_all(strCmd, "%s", hashNewTip.GetHex());
525+
boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex());
523526
boost::thread t(runCommand, strCmd); // thread runs free
524527
}
525528

src/main.cpp

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2606,37 +2606,41 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
26062606
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
26072607

26082608
// Notifications/callbacks that can run without cs_main
2609-
if (!fInitialDownload) {
2610-
// Find the hashes of all blocks that weren't previously in the best chain.
2611-
std::vector<uint256> vHashes;
2612-
CBlockIndex *pindexToAnnounce = pindexNewTip;
2613-
while (pindexToAnnounce != pindexFork) {
2614-
vHashes.push_back(pindexToAnnounce->GetBlockHash());
2615-
pindexToAnnounce = pindexToAnnounce->pprev;
2616-
if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
2617-
// Limit announcements in case of a huge reorganization.
2618-
// Rely on the peer's synchronization mechanism in that case.
2619-
break;
2609+
// Always notify the UI if a new block tip was connected
2610+
if (pindexFork != pindexNewTip) {
2611+
uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
2612+
2613+
if (!fInitialDownload) {
2614+
// Find the hashes of all blocks that weren't previously in the best chain.
2615+
std::vector<uint256> vHashes;
2616+
CBlockIndex *pindexToAnnounce = pindexNewTip;
2617+
while (pindexToAnnounce != pindexFork) {
2618+
vHashes.push_back(pindexToAnnounce->GetBlockHash());
2619+
pindexToAnnounce = pindexToAnnounce->pprev;
2620+
if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
2621+
// Limit announcements in case of a huge reorganization.
2622+
// Rely on the peer's synchronization mechanism in that case.
2623+
break;
2624+
}
26202625
}
2621-
}
2622-
// Relay inventory, but don't relay old inventory during initial block download.
2623-
int nBlockEstimate = 0;
2624-
if (fCheckpointsEnabled)
2625-
nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints());
2626-
{
2627-
LOCK(cs_vNodes);
2628-
BOOST_FOREACH(CNode* pnode, vNodes) {
2629-
if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) {
2630-
BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) {
2631-
pnode->PushBlockHash(hash);
2626+
// Relay inventory, but don't relay old inventory during initial block download.
2627+
int nBlockEstimate = 0;
2628+
if (fCheckpointsEnabled)
2629+
nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints());
2630+
{
2631+
LOCK(cs_vNodes);
2632+
BOOST_FOREACH(CNode* pnode, vNodes) {
2633+
if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) {
2634+
BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) {
2635+
pnode->PushBlockHash(hash);
2636+
}
26322637
}
26332638
}
26342639
}
2635-
}
2636-
// Notify external listeners about the new tip.
2637-
if (!vHashes.empty()) {
2638-
GetMainSignals().UpdatedBlockTip(pindexNewTip);
2639-
uiInterface.NotifyBlockTip(vHashes.front());
2640+
// Notify external listeners about the new tip.
2641+
if (!vHashes.empty()) {
2642+
GetMainSignals().UpdatedBlockTip(pindexNewTip);
2643+
}
26402644
}
26412645
}
26422646
} while(pindexMostWork != chainActive.Tip());

src/qt/bitcoingui.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
453453
setNumConnections(clientModel->getNumConnections());
454454
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
455455

456-
setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate());
457-
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime)));
456+
setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL));
457+
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(setNumBlocks(int,QDateTime,double)));
458458

459459
// Receive and report messages from client model
460460
connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
@@ -682,7 +682,7 @@ void BitcoinGUI::setNumConnections(int count)
682682
labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
683683
}
684684

685-
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate)
685+
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress)
686686
{
687687
if(!clientModel)
688688
return;
@@ -759,7 +759,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate)
759759
progressBarLabel->setVisible(true);
760760
progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
761761
progressBar->setMaximum(1000000000);
762-
progressBar->setValue(clientModel->getVerificationProgress() * 1000000000.0 + 0.5);
762+
progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
763763
progressBar->setVisible(true);
764764

765765
tooltip = tr("Catching up...") + QString("<br>") + tooltip;

src/qt/bitcoingui.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public Q_SLOTS:
150150
/** Set number of connections shown in the UI */
151151
void setNumConnections(int count);
152152
/** Set number of blocks and last block date shown in the UI */
153-
void setNumBlocks(int count, const QDateTime& blockDate);
153+
void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress);
154154

155155
/** Notify the user of an event from the core network or transaction handling code.
156156
@param[in] title the message box / notification title

src/qt/clientmodel.cpp

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,16 @@
2222
#include <QDebug>
2323
#include <QTimer>
2424

25+
class CBlockIndex;
26+
2527
static const int64_t nClientStartupTime = GetTime();
28+
static int64_t nLastBlockTipUpdateNotification = 0;
2629

2730
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
2831
QObject(parent),
2932
optionsModel(optionsModel),
3033
peerTableModel(0),
3134
banTableModel(0),
32-
cachedNumBlocks(0),
33-
cachedBlockDate(QDateTime()),
34-
cachedReindexing(0),
35-
cachedImporting(0),
3635
pollTimer(0)
3736
{
3837
peerTableModel = new PeerTableModel(this);
@@ -99,40 +98,21 @@ size_t ClientModel::getMempoolDynamicUsage() const
9998
return mempool.DynamicMemoryUsage();
10099
}
101100

102-
double ClientModel::getVerificationProgress() const
101+
double ClientModel::getVerificationProgress(const CBlockIndex *tipIn) const
103102
{
104-
LOCK(cs_main);
105-
return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip());
103+
CBlockIndex *tip = const_cast<CBlockIndex *>(tipIn);
104+
if (!tip)
105+
{
106+
LOCK(cs_main);
107+
tip = chainActive.Tip();
108+
}
109+
return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), tip);
106110
}
107111

108112
void ClientModel::updateTimer()
109113
{
110-
// Get required lock upfront. This avoids the GUI from getting stuck on
111-
// periodical polls if the core is holding the locks for a longer time -
112-
// for example, during a wallet rescan.
113-
TRY_LOCK(cs_main, lockMain);
114-
if (!lockMain)
115-
return;
116-
117-
// Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
118-
// Periodically check and update with a timer.
119-
int newNumBlocks = getNumBlocks();
120-
QDateTime newBlockDate = getLastBlockDate();
121-
122-
// check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state
123-
if (cachedNumBlocks != newNumBlocks ||
124-
cachedBlockDate != newBlockDate ||
125-
cachedReindexing != fReindex ||
126-
cachedImporting != fImporting)
127-
{
128-
cachedNumBlocks = newNumBlocks;
129-
cachedBlockDate = newBlockDate;
130-
cachedReindexing = fReindex;
131-
cachedImporting = fImporting;
132-
133-
Q_EMIT numBlocksChanged(newNumBlocks, newBlockDate);
134-
}
135-
114+
// no locking required at this point
115+
// the following calls will aquire the required lock
136116
Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage());
137117
Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
138118
}
@@ -261,13 +241,31 @@ static void BannedListChanged(ClientModel *clientmodel)
261241
QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection);
262242
}
263243

244+
static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex)
245+
{
246+
// lock free async UI updates in case we have a new block tip
247+
// during initial sync, only update the UI if the last update
248+
// was > 250ms (MODEL_UPDATE_DELAY) ago
249+
int64_t now = 0;
250+
if (initialSync)
251+
now = GetTimeMillis();
252+
253+
// if we are in-sync, update the UI regardless of last update time
254+
if (!initialSync || now - nLastBlockTipUpdateNotification > MODEL_UPDATE_DELAY) {
255+
//pass a async signal to the UI thread
256+
Q_EMIT clientmodel->numBlocksChanged(pIndex->nHeight, QDateTime::fromTime_t(pIndex->GetBlockTime()), clientmodel->getVerificationProgress(pIndex));
257+
nLastBlockTipUpdateNotification = now;
258+
}
259+
}
260+
264261
void ClientModel::subscribeToCoreSignals()
265262
{
266263
// Connect signals to client
267264
uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
268265
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
269266
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
270267
uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
268+
uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2));
271269
}
272270

273271
void ClientModel::unsubscribeFromCoreSignals()
@@ -277,4 +275,5 @@ void ClientModel::unsubscribeFromCoreSignals()
277275
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
278276
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
279277
uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
278+
uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2));
280279
}

src/qt/clientmodel.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class PeerTableModel;
1515
class TransactionTableModel;
1616

1717
class CWallet;
18+
class CBlockIndex;
1819

1920
QT_BEGIN_NAMESPACE
2021
class QTimer;
@@ -59,7 +60,7 @@ class ClientModel : public QObject
5960
quint64 getTotalBytesRecv() const;
6061
quint64 getTotalBytesSent() const;
6162

62-
double getVerificationProgress() const;
63+
double getVerificationProgress(const CBlockIndex *tip) const;
6364
QDateTime getLastBlockDate() const;
6465

6566
//! Return true if core is doing initial block download
@@ -81,19 +82,14 @@ class ClientModel : public QObject
8182
PeerTableModel *peerTableModel;
8283
BanTableModel *banTableModel;
8384

84-
int cachedNumBlocks;
85-
QDateTime cachedBlockDate;
86-
bool cachedReindexing;
87-
bool cachedImporting;
88-
8985
QTimer *pollTimer;
9086

9187
void subscribeToCoreSignals();
9288
void unsubscribeFromCoreSignals();
9389

9490
Q_SIGNALS:
9591
void numConnectionsChanged(int count);
96-
void numBlocksChanged(int count, const QDateTime& blockDate);
92+
void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress);
9793
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes);
9894
void alertsChanged(const QString &warnings);
9995
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);

src/qt/rpcconsole.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,8 @@ void RPCConsole::setClientModel(ClientModel *model)
343343
setNumConnections(model->getNumConnections());
344344
connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
345345

346-
setNumBlocks(model->getNumBlocks(), model->getLastBlockDate());
347-
connect(model, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime)));
346+
setNumBlocks(model->getNumBlocks(), model->getLastBlockDate(), model->getVerificationProgress(NULL));
347+
connect(model, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(setNumBlocks(int,QDateTime,double)));
348348

349349
updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent());
350350
connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
@@ -525,7 +525,7 @@ void RPCConsole::setNumConnections(int count)
525525
ui->numberOfConnections->setText(connections);
526526
}
527527

528-
void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate)
528+
void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress)
529529
{
530530
ui->numberOfBlocks->setText(QString::number(count));
531531
ui->lastBlockTime->setText(blockDate.toString());

src/qt/rpcconsole.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public Q_SLOTS:
8383
/** Set number of connections shown in the UI */
8484
void setNumConnections(int count);
8585
/** Set number of blocks and last block date shown in the UI */
86-
void setNumBlocks(int count, const QDateTime& blockDate);
86+
void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress);
8787
/** Set size (number of transactions and memory usage) of the mempool in the UI */
8888
void setMempoolSize(long numberOfTxs, size_t dynUsage);
8989
/** Go forward or back in history */

src/qt/sendcoinsdialog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ void SendCoinsDialog::setClientModel(ClientModel *clientModel)
124124
this->clientModel = clientModel;
125125

126126
if (clientModel) {
127-
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(updateSmartFeeLabel()));
127+
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(updateSmartFeeLabel()));
128128
}
129129
}
130130

src/ui_interface.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
class CBasicKeyStore;
1616
class CWallet;
1717
class uint256;
18+
class CBlockIndex;
1819

1920
/** General change type (added, updated, removed). */
2021
enum ChangeType
@@ -94,7 +95,7 @@ class CClientUIInterface
9495
boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
9596

9697
/** New block has been accepted */
97-
boost::signals2::signal<void (const uint256& hash)> NotifyBlockTip;
98+
boost::signals2::signal<void (bool, const CBlockIndex *)> NotifyBlockTip;
9899

99100
/** Banlist did change. */
100101
boost::signals2::signal<void (void)> BannedListChanged;

0 commit comments

Comments
 (0)