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)
This commit is contained in:
commit
96b802510d
10 changed files with 83 additions and 80 deletions
|
@ -515,11 +515,14 @@ std::string LicenseInfo()
|
||||||
"\n";
|
"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BlockNotifyCallback(const uint256& hashNewTip)
|
static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex)
|
||||||
{
|
{
|
||||||
|
if (initialSync || !pBlockIndex)
|
||||||
|
return;
|
||||||
|
|
||||||
std::string strCmd = GetArg("-blocknotify", "");
|
std::string strCmd = GetArg("-blocknotify", "");
|
||||||
|
|
||||||
boost::replace_all(strCmd, "%s", hashNewTip.GetHex());
|
boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex());
|
||||||
boost::thread t(runCommand, strCmd); // thread runs free
|
boost::thread t(runCommand, strCmd); // thread runs free
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2606,6 +2606,10 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
|
||||||
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
|
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
|
||||||
|
|
||||||
// Notifications/callbacks that can run without cs_main
|
// Notifications/callbacks that can run without cs_main
|
||||||
|
// Always notify the UI if a new block tip was connected
|
||||||
|
if (pindexFork != pindexNewTip) {
|
||||||
|
uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
|
||||||
|
|
||||||
if (!fInitialDownload) {
|
if (!fInitialDownload) {
|
||||||
// Find the hashes of all blocks that weren't previously in the best chain.
|
// Find the hashes of all blocks that weren't previously in the best chain.
|
||||||
std::vector<uint256> vHashes;
|
std::vector<uint256> vHashes;
|
||||||
|
@ -2636,7 +2640,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
|
||||||
// Notify external listeners about the new tip.
|
// Notify external listeners about the new tip.
|
||||||
if (!vHashes.empty()) {
|
if (!vHashes.empty()) {
|
||||||
GetMainSignals().UpdatedBlockTip(pindexNewTip);
|
GetMainSignals().UpdatedBlockTip(pindexNewTip);
|
||||||
uiInterface.NotifyBlockTip(vHashes.front());
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while(pindexMostWork != chainActive.Tip());
|
} while(pindexMostWork != chainActive.Tip());
|
||||||
|
|
|
@ -453,8 +453,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
|
||||||
setNumConnections(clientModel->getNumConnections());
|
setNumConnections(clientModel->getNumConnections());
|
||||||
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
|
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
|
||||||
|
|
||||||
setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate());
|
setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL));
|
||||||
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime)));
|
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(setNumBlocks(int,QDateTime,double)));
|
||||||
|
|
||||||
// Receive and report messages from client model
|
// Receive and report messages from client model
|
||||||
connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
|
connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
|
||||||
|
@ -682,7 +682,7 @@ void BitcoinGUI::setNumConnections(int count)
|
||||||
labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
|
labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate)
|
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress)
|
||||||
{
|
{
|
||||||
if(!clientModel)
|
if(!clientModel)
|
||||||
return;
|
return;
|
||||||
|
@ -759,7 +759,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate)
|
||||||
progressBarLabel->setVisible(true);
|
progressBarLabel->setVisible(true);
|
||||||
progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
|
progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
|
||||||
progressBar->setMaximum(1000000000);
|
progressBar->setMaximum(1000000000);
|
||||||
progressBar->setValue(clientModel->getVerificationProgress() * 1000000000.0 + 0.5);
|
progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
|
||||||
progressBar->setVisible(true);
|
progressBar->setVisible(true);
|
||||||
|
|
||||||
tooltip = tr("Catching up...") + QString("<br>") + tooltip;
|
tooltip = tr("Catching up...") + QString("<br>") + tooltip;
|
||||||
|
|
|
@ -150,7 +150,7 @@ public Q_SLOTS:
|
||||||
/** Set number of connections shown in the UI */
|
/** Set number of connections shown in the UI */
|
||||||
void setNumConnections(int count);
|
void setNumConnections(int count);
|
||||||
/** Set number of blocks and last block date shown in the UI */
|
/** Set number of blocks and last block date shown in the UI */
|
||||||
void setNumBlocks(int count, const QDateTime& blockDate);
|
void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress);
|
||||||
|
|
||||||
/** Notify the user of an event from the core network or transaction handling code.
|
/** Notify the user of an event from the core network or transaction handling code.
|
||||||
@param[in] title the message box / notification title
|
@param[in] title the message box / notification title
|
||||||
|
|
|
@ -22,17 +22,16 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
class CBlockIndex;
|
||||||
|
|
||||||
static const int64_t nClientStartupTime = GetTime();
|
static const int64_t nClientStartupTime = GetTime();
|
||||||
|
static int64_t nLastBlockTipUpdateNotification = 0;
|
||||||
|
|
||||||
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
|
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
optionsModel(optionsModel),
|
optionsModel(optionsModel),
|
||||||
peerTableModel(0),
|
peerTableModel(0),
|
||||||
banTableModel(0),
|
banTableModel(0),
|
||||||
cachedNumBlocks(0),
|
|
||||||
cachedBlockDate(QDateTime()),
|
|
||||||
cachedReindexing(0),
|
|
||||||
cachedImporting(0),
|
|
||||||
pollTimer(0)
|
pollTimer(0)
|
||||||
{
|
{
|
||||||
peerTableModel = new PeerTableModel(this);
|
peerTableModel = new PeerTableModel(this);
|
||||||
|
@ -99,40 +98,21 @@ size_t ClientModel::getMempoolDynamicUsage() const
|
||||||
return mempool.DynamicMemoryUsage();
|
return mempool.DynamicMemoryUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
double ClientModel::getVerificationProgress() const
|
double ClientModel::getVerificationProgress(const CBlockIndex *tipIn) const
|
||||||
{
|
{
|
||||||
|
CBlockIndex *tip = const_cast<CBlockIndex *>(tipIn);
|
||||||
|
if (!tip)
|
||||||
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip());
|
tip = chainActive.Tip();
|
||||||
|
}
|
||||||
|
return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), tip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientModel::updateTimer()
|
void ClientModel::updateTimer()
|
||||||
{
|
{
|
||||||
// Get required lock upfront. This avoids the GUI from getting stuck on
|
// no locking required at this point
|
||||||
// periodical polls if the core is holding the locks for a longer time -
|
// the following calls will aquire the required lock
|
||||||
// for example, during a wallet rescan.
|
|
||||||
TRY_LOCK(cs_main, lockMain);
|
|
||||||
if (!lockMain)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
|
|
||||||
// Periodically check and update with a timer.
|
|
||||||
int newNumBlocks = getNumBlocks();
|
|
||||||
QDateTime newBlockDate = getLastBlockDate();
|
|
||||||
|
|
||||||
// check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state
|
|
||||||
if (cachedNumBlocks != newNumBlocks ||
|
|
||||||
cachedBlockDate != newBlockDate ||
|
|
||||||
cachedReindexing != fReindex ||
|
|
||||||
cachedImporting != fImporting)
|
|
||||||
{
|
|
||||||
cachedNumBlocks = newNumBlocks;
|
|
||||||
cachedBlockDate = newBlockDate;
|
|
||||||
cachedReindexing = fReindex;
|
|
||||||
cachedImporting = fImporting;
|
|
||||||
|
|
||||||
Q_EMIT numBlocksChanged(newNumBlocks, newBlockDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage());
|
Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage());
|
||||||
Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
|
Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
|
||||||
}
|
}
|
||||||
|
@ -261,6 +241,23 @@ static void BannedListChanged(ClientModel *clientmodel)
|
||||||
QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex)
|
||||||
|
{
|
||||||
|
// lock free async UI updates in case we have a new block tip
|
||||||
|
// during initial sync, only update the UI if the last update
|
||||||
|
// was > 250ms (MODEL_UPDATE_DELAY) ago
|
||||||
|
int64_t now = 0;
|
||||||
|
if (initialSync)
|
||||||
|
now = GetTimeMillis();
|
||||||
|
|
||||||
|
// if we are in-sync, update the UI regardless of last update time
|
||||||
|
if (!initialSync || now - nLastBlockTipUpdateNotification > MODEL_UPDATE_DELAY) {
|
||||||
|
//pass a async signal to the UI thread
|
||||||
|
Q_EMIT clientmodel->numBlocksChanged(pIndex->nHeight, QDateTime::fromTime_t(pIndex->GetBlockTime()), clientmodel->getVerificationProgress(pIndex));
|
||||||
|
nLastBlockTipUpdateNotification = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClientModel::subscribeToCoreSignals()
|
void ClientModel::subscribeToCoreSignals()
|
||||||
{
|
{
|
||||||
// Connect signals to client
|
// Connect signals to client
|
||||||
|
@ -268,6 +265,7 @@ void ClientModel::subscribeToCoreSignals()
|
||||||
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
||||||
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
||||||
uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
|
uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
|
||||||
|
uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientModel::unsubscribeFromCoreSignals()
|
void ClientModel::unsubscribeFromCoreSignals()
|
||||||
|
@ -277,4 +275,5 @@ void ClientModel::unsubscribeFromCoreSignals()
|
||||||
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
||||||
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
||||||
uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
|
uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
|
||||||
|
uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ class PeerTableModel;
|
||||||
class TransactionTableModel;
|
class TransactionTableModel;
|
||||||
|
|
||||||
class CWallet;
|
class CWallet;
|
||||||
|
class CBlockIndex;
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
@ -59,7 +60,7 @@ public:
|
||||||
quint64 getTotalBytesRecv() const;
|
quint64 getTotalBytesRecv() const;
|
||||||
quint64 getTotalBytesSent() const;
|
quint64 getTotalBytesSent() const;
|
||||||
|
|
||||||
double getVerificationProgress() const;
|
double getVerificationProgress(const CBlockIndex *tip) const;
|
||||||
QDateTime getLastBlockDate() const;
|
QDateTime getLastBlockDate() const;
|
||||||
|
|
||||||
//! Return true if core is doing initial block download
|
//! Return true if core is doing initial block download
|
||||||
|
@ -81,11 +82,6 @@ private:
|
||||||
PeerTableModel *peerTableModel;
|
PeerTableModel *peerTableModel;
|
||||||
BanTableModel *banTableModel;
|
BanTableModel *banTableModel;
|
||||||
|
|
||||||
int cachedNumBlocks;
|
|
||||||
QDateTime cachedBlockDate;
|
|
||||||
bool cachedReindexing;
|
|
||||||
bool cachedImporting;
|
|
||||||
|
|
||||||
QTimer *pollTimer;
|
QTimer *pollTimer;
|
||||||
|
|
||||||
void subscribeToCoreSignals();
|
void subscribeToCoreSignals();
|
||||||
|
@ -93,7 +89,7 @@ private:
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void numConnectionsChanged(int count);
|
void numConnectionsChanged(int count);
|
||||||
void numBlocksChanged(int count, const QDateTime& blockDate);
|
void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress);
|
||||||
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes);
|
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes);
|
||||||
void alertsChanged(const QString &warnings);
|
void alertsChanged(const QString &warnings);
|
||||||
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);
|
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);
|
||||||
|
|
|
@ -343,8 +343,8 @@ void RPCConsole::setClientModel(ClientModel *model)
|
||||||
setNumConnections(model->getNumConnections());
|
setNumConnections(model->getNumConnections());
|
||||||
connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
|
connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
|
||||||
|
|
||||||
setNumBlocks(model->getNumBlocks(), model->getLastBlockDate());
|
setNumBlocks(model->getNumBlocks(), model->getLastBlockDate(), model->getVerificationProgress(NULL));
|
||||||
connect(model, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime)));
|
connect(model, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(setNumBlocks(int,QDateTime,double)));
|
||||||
|
|
||||||
updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent());
|
updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent());
|
||||||
connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
|
connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
|
||||||
|
@ -525,7 +525,7 @@ void RPCConsole::setNumConnections(int count)
|
||||||
ui->numberOfConnections->setText(connections);
|
ui->numberOfConnections->setText(connections);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate)
|
void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress)
|
||||||
{
|
{
|
||||||
ui->numberOfBlocks->setText(QString::number(count));
|
ui->numberOfBlocks->setText(QString::number(count));
|
||||||
ui->lastBlockTime->setText(blockDate.toString());
|
ui->lastBlockTime->setText(blockDate.toString());
|
||||||
|
|
|
@ -83,7 +83,7 @@ public Q_SLOTS:
|
||||||
/** Set number of connections shown in the UI */
|
/** Set number of connections shown in the UI */
|
||||||
void setNumConnections(int count);
|
void setNumConnections(int count);
|
||||||
/** Set number of blocks and last block date shown in the UI */
|
/** Set number of blocks and last block date shown in the UI */
|
||||||
void setNumBlocks(int count, const QDateTime& blockDate);
|
void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress);
|
||||||
/** Set size (number of transactions and memory usage) of the mempool in the UI */
|
/** Set size (number of transactions and memory usage) of the mempool in the UI */
|
||||||
void setMempoolSize(long numberOfTxs, size_t dynUsage);
|
void setMempoolSize(long numberOfTxs, size_t dynUsage);
|
||||||
/** Go forward or back in history */
|
/** Go forward or back in history */
|
||||||
|
|
|
@ -124,7 +124,7 @@ void SendCoinsDialog::setClientModel(ClientModel *clientModel)
|
||||||
this->clientModel = clientModel;
|
this->clientModel = clientModel;
|
||||||
|
|
||||||
if (clientModel) {
|
if (clientModel) {
|
||||||
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(updateSmartFeeLabel()));
|
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(updateSmartFeeLabel()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
class CBasicKeyStore;
|
class CBasicKeyStore;
|
||||||
class CWallet;
|
class CWallet;
|
||||||
class uint256;
|
class uint256;
|
||||||
|
class CBlockIndex;
|
||||||
|
|
||||||
/** General change type (added, updated, removed). */
|
/** General change type (added, updated, removed). */
|
||||||
enum ChangeType
|
enum ChangeType
|
||||||
|
@ -94,7 +95,7 @@ public:
|
||||||
boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
|
boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
|
||||||
|
|
||||||
/** New block has been accepted */
|
/** New block has been accepted */
|
||||||
boost::signals2::signal<void (const uint256& hash)> NotifyBlockTip;
|
boost::signals2::signal<void (bool, const CBlockIndex *)> NotifyBlockTip;
|
||||||
|
|
||||||
/** Banlist did change. */
|
/** Banlist did change. */
|
||||||
boost::signals2::signal<void (void)> BannedListChanged;
|
boost::signals2::signal<void (void)> BannedListChanged;
|
||||||
|
|
Loading…
Reference in a new issue