From 3add23454624c4c79c9eebc060b6fbed4e3131a7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 13 Aug 2022 16:27:50 -0400 Subject: ui: show header pre-synchronization progress --- src/qt/bitcoin.cpp | 2 ++ src/qt/bitcoingui.cpp | 26 ++++++++++++++++++-------- src/qt/bitcoingui.h | 5 +++-- src/qt/clientmodel.cpp | 16 ++++++++-------- src/qt/clientmodel.h | 10 ++++++++-- src/qt/modaloverlay.cpp | 12 ++++++++++-- src/qt/modaloverlay.h | 3 ++- src/qt/rpcconsole.cpp | 6 +++--- src/qt/rpcconsole.h | 4 ++-- src/qt/sendcoinsdialog.cpp | 2 +- src/qt/sendcoinsdialog.h | 4 ++-- 11 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 33c60deafb..cc01e4d54a 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -75,6 +75,7 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin) Q_DECLARE_METATYPE(bool*) Q_DECLARE_METATYPE(CAmount) Q_DECLARE_METATYPE(SynchronizationState) +Q_DECLARE_METATYPE(SyncType) Q_DECLARE_METATYPE(uint256) static void RegisterMetaTypes() @@ -82,6 +83,7 @@ static void RegisterMetaTypes() // Register meta types used for QMetaObject::invokeMethod and Qt::QueuedConnection qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); #ifdef ENABLE_WALLET qRegisterMetaType(); #endif diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 90f228803c..1c1328e000 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -615,8 +615,8 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH connect(_clientModel, &ClientModel::numConnectionsChanged, this, &BitcoinGUI::setNumConnections); connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive); - modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromSecsSinceEpoch(tip_info->header_time)); - setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), tip_info->verification_progress, false, SynchronizationState::INIT_DOWNLOAD); + modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromSecsSinceEpoch(tip_info->header_time), /*presync=*/false); + setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), tip_info->verification_progress, SyncType::BLOCK_SYNC, SynchronizationState::INIT_DOWNLOAD); connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks); // Receive and report messages from client model @@ -1026,6 +1026,13 @@ void BitcoinGUI::updateHeadersSyncProgressLabel() progressBarLabel->setText(tr("Syncing Headers (%1%)…").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1))); } +void BitcoinGUI::updateHeadersPresyncProgressLabel(int64_t height, const QDateTime& blockDate) +{ + int estHeadersLeft = blockDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing; + if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC) + progressBarLabel->setText(tr("Pre-syncing Headers (%1%)…").arg(QString::number(100.0 / (height+estHeadersLeft)*height, 'f', 1))); +} + void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab) { if (!clientModel || !clientModel->getOptionsModel()) @@ -1039,7 +1046,7 @@ void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab) GUIUtil::ShowModalDialogAsynchronously(dlg); } -void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state) +void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state) { // Disabling macOS App Nap on initial sync, disk and reindex operations. #ifdef Q_OS_MACOS @@ -1052,8 +1059,8 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer if (modalOverlay) { - if (header) - modalOverlay->setKnownBestHeight(count, blockDate); + if (synctype != SyncType::BLOCK_SYNC) + modalOverlay->setKnownBestHeight(count, blockDate, synctype == SyncType::HEADER_PRESYNC); else modalOverlay->tipUpdate(count, blockDate, nVerificationProgress); } @@ -1067,7 +1074,10 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer enum BlockSource blockSource = clientModel->getBlockSource(); switch (blockSource) { case BlockSource::NETWORK: - if (header) { + if (synctype == SyncType::HEADER_PRESYNC) { + updateHeadersPresyncProgressLabel(count, blockDate); + return; + } else if (synctype == SyncType::HEADER_SYNC) { updateHeadersSyncProgressLabel(); return; } @@ -1075,7 +1085,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer updateHeadersSyncProgressLabel(); break; case BlockSource::DISK: - if (header) { + if (synctype != SyncType::BLOCK_SYNC) { progressBarLabel->setText(tr("Indexing blocks on disk…")); } else { progressBarLabel->setText(tr("Processing blocks on disk…")); @@ -1085,7 +1095,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer progressBarLabel->setText(tr("Reindexing blocks on disk…")); break; case BlockSource::NONE: - if (header) { + if (synctype != SyncType::BLOCK_SYNC) { return; } progressBarLabel->setText(tr("Connecting to peers…")); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index b2e13245e1..912e9b95aa 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -10,6 +10,7 @@ #endif #include +#include #include #include @@ -28,7 +29,6 @@ #include -class ClientModel; class NetworkStyle; class Notificator; class OptionsModel; @@ -208,6 +208,7 @@ private: void updateNetworkState(); void updateHeadersSyncProgressLabel(); + void updateHeadersPresyncProgressLabel(int64_t height, const QDateTime& blockDate); /** Open the OptionsDialog on the specified tab index */ void openOptionsDialogWithTab(OptionsDialog::Tab tab); @@ -226,7 +227,7 @@ public Q_SLOTS: /** Set network state shown in the UI */ void setNetworkActive(bool network_active); /** Set number of blocks and last block date shown in the UI */ - void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state); + void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state); /** Notify the user of an event from the core network or transaction handling code. @param[in] title the message box / notification title diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 927554eaaf..092ffe7e5b 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -215,26 +215,26 @@ QString ClientModel::blocksDir() const return GUIUtil::PathToQString(gArgs.GetBlocksDirPath()); } -void ClientModel::TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, bool header) +void ClientModel::TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, SyncType synctype) { - if (header) { + if (synctype == SyncType::HEADER_SYNC) { // cache best headers time and height to reduce future cs_main locks cachedBestHeaderHeight = tip.block_height; cachedBestHeaderTime = tip.block_time; - } else { + } else if (synctype == SyncType::BLOCK_SYNC) { m_cached_num_blocks = tip.block_height; WITH_LOCK(m_cached_tip_mutex, m_cached_tip_blocks = tip.block_hash;); } // Throttle GUI notifications about (a) blocks during initial sync, and (b) both blocks and headers during reindex. - const bool throttle = (sync_state != SynchronizationState::POST_INIT && !header) || sync_state == SynchronizationState::INIT_REINDEX; + const bool throttle = (sync_state != SynchronizationState::POST_INIT && synctype == SyncType::BLOCK_SYNC) || sync_state == SynchronizationState::INIT_REINDEX; const int64_t now = throttle ? GetTimeMillis() : 0; - int64_t& nLastUpdateNotification = header ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; + int64_t& nLastUpdateNotification = synctype != SyncType::BLOCK_SYNC ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; if (throttle && now < nLastUpdateNotification + count_milliseconds(MODEL_UPDATE_DELAY)) { return; } - Q_EMIT numBlocksChanged(tip.block_height, QDateTime::fromSecsSinceEpoch(tip.block_time), verification_progress, header, sync_state); + Q_EMIT numBlocksChanged(tip.block_height, QDateTime::fromSecsSinceEpoch(tip.block_time), verification_progress, synctype, sync_state); nLastUpdateNotification = now; } @@ -264,11 +264,11 @@ void ClientModel::subscribeToCoreSignals() }); m_handler_notify_block_tip = m_node.handleNotifyBlockTip( [this](SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress) { - TipChanged(sync_state, tip, verification_progress, /*header=*/false); + TipChanged(sync_state, tip, verification_progress, SyncType::BLOCK_SYNC); }); m_handler_notify_header_tip = m_node.handleNotifyHeaderTip( [this](SynchronizationState sync_state, interfaces::BlockTip tip, bool presync) { - if (!presync) TipChanged(sync_state, tip, /*verification_progress=*/0.0, /*header=*/true); + TipChanged(sync_state, tip, /*verification_progress=*/0.0, presync ? SyncType::HEADER_PRESYNC : SyncType::HEADER_SYNC); }); } diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 81f03a58ec..4a6abd6a76 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -37,6 +37,12 @@ enum class BlockSource { NETWORK }; +enum class SyncType { + HEADER_PRESYNC, + HEADER_SYNC, + BLOCK_SYNC +}; + enum NumConnections { CONNECTIONS_NONE = 0, CONNECTIONS_IN = (1U << 0), @@ -105,13 +111,13 @@ private: //! A thread to interact with m_node asynchronously QThread* const m_thread; - void TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, bool header) EXCLUSIVE_LOCKS_REQUIRED(!m_cached_tip_mutex); + void TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, SyncType synctype) EXCLUSIVE_LOCKS_REQUIRED(!m_cached_tip_mutex); void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); Q_SIGNALS: void numConnectionsChanged(int count); - void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state); + void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType header, SynchronizationState sync_state); void mempoolSizeChanged(long count, size_t mempoolSizeInBytes); void networkActiveChanged(bool networkActive); void alertsChanged(const QString &warnings); diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 97ee75a31f..dfa33764f6 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -78,13 +78,16 @@ bool ModalOverlay::event(QEvent* ev) { return QWidget::event(ev); } -void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate) +void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate, bool presync) { - if (count > bestHeaderHeight) { + if (!presync && count > bestHeaderHeight) { bestHeaderHeight = count; bestHeaderDate = blockDate; UpdateHeaderSyncLabel(); } + if (presync) { + UpdateHeaderPresyncLabel(count, blockDate); + } } void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress) @@ -158,6 +161,11 @@ void ModalOverlay::UpdateHeaderSyncLabel() { ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1, %2%)…").arg(bestHeaderHeight).arg(QString::number(100.0 / (bestHeaderHeight + est_headers_left) * bestHeaderHeight, 'f', 1))); } +void ModalOverlay::UpdateHeaderPresyncLabel(int height, const QDateTime& blockDate) { + int est_headers_left = blockDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing; + ui->numberOfBlocksLeft->setText(tr("Unknown. Pre-syncing Headers (%1, %2%)…").arg(height).arg(QString::number(100.0 / (height + est_headers_left) * height, 'f', 1))); +} + void ModalOverlay::toggleVisibility() { showHide(layerIsVisible, true); diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h index 1d8af5cbf6..682c94cd01 100644 --- a/src/qt/modaloverlay.h +++ b/src/qt/modaloverlay.h @@ -26,7 +26,7 @@ public: ~ModalOverlay(); void tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress); - void setKnownBestHeight(int count, const QDateTime& blockDate); + void setKnownBestHeight(int count, const QDateTime& blockDate, bool presync); // will show or hide the modal layer void showHide(bool hide = false, bool userRequested = false); @@ -52,6 +52,7 @@ private: bool userClosed; QPropertyAnimation m_animation; void UpdateHeaderSyncLabel(); + void UpdateHeaderPresyncLabel(int height, const QDateTime& blockDate); }; #endif // BITCOIN_QT_MODALOVERLAY_H diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 70fccdef1c..8c0b8cc3ab 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -661,7 +661,7 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ setNumConnections(model->getNumConnections()); connect(model, &ClientModel::numConnectionsChanged, this, &RPCConsole::setNumConnections); - setNumBlocks(bestblock_height, QDateTime::fromSecsSinceEpoch(bestblock_date), verification_progress, false); + setNumBlocks(bestblock_height, QDateTime::fromSecsSinceEpoch(bestblock_date), verification_progress, SyncType::BLOCK_SYNC); connect(model, &ClientModel::numBlocksChanged, this, &RPCConsole::setNumBlocks); updateNetworkState(); @@ -973,9 +973,9 @@ void RPCConsole::setNetworkActive(bool networkActive) updateNetworkState(); } -void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers) +void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype) { - if (!headers) { + if (synctype == SyncType::BLOCK_SYNC) { ui->numberOfBlocks->setText(QString::number(count)); ui->lastBlockTime->setText(blockDate.toString()); } diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 1a54fe0cad..a3c713e966 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -9,6 +9,7 @@ #include #endif +#include #include #include @@ -19,7 +20,6 @@ #include #include -class ClientModel; class PlatformStyle; class RPCExecutor; class RPCTimerInterface; @@ -121,7 +121,7 @@ public Q_SLOTS: /** Set network state shown in the UI */ void setNetworkActive(bool networkActive); /** Set number of blocks and last block date shown in the UI */ - void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers); + void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype); /** Set size (number of transactions and memory usage) of the mempool in the UI */ void setMempoolSize(long numberOfTxs, size_t dynUsage); /** Go forward or back in history */ diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index a75c1098a5..53c352b393 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -839,7 +839,7 @@ void SendCoinsDialog::updateCoinControlState() m_coin_control->fAllowWatchOnly = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner(); } -void SendCoinsDialog::updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state) { +void SendCoinsDialog::updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state) { if (sync_state == SynchronizationState::POST_INIT) { updateSmartFeeLabel(); } diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index b58d4690a0..dcdf189532 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -5,6 +5,7 @@ #ifndef BITCOIN_QT_SENDCOINSDIALOG_H #define BITCOIN_QT_SENDCOINSDIALOG_H +#include #include #include @@ -12,7 +13,6 @@ #include #include -class ClientModel; class PlatformStyle; class SendCoinsEntry; class SendCoinsRecipient; @@ -111,7 +111,7 @@ private Q_SLOTS: void coinControlClipboardLowOutput(); void coinControlClipboardChange(); void updateFeeSectionControls(); - void updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state); + void updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state); void updateSmartFeeLabel(); Q_SIGNALS: -- cgit v1.2.3