diff --git a/src/qml/components/BlockClock.qml b/src/qml/components/BlockClock.qml index f7210aa534..8397180ee5 100644 --- a/src/qml/components/BlockClock.qml +++ b/src/qml/components/BlockClock.qml @@ -24,7 +24,7 @@ Item { property alias subText: subText.text property int headerSize: 32 property bool connected: nodeModel.numOutboundPeers > 0 - property bool synced: nodeModel.verificationProgress > 0.999 + property bool synced: !nodeModel.inIBD property string syncProgress: formatProgressPercentage(nodeModel.verificationProgress * 100) property bool paused: false property var syncState: formatRemainingSyncTime(nodeModel.remainingSyncTime) @@ -49,7 +49,7 @@ Item { verificationProgress: nodeModel.verificationProgress paused: root.paused connected: root.connected - synced: nodeModel.verificationProgress > 0.999 + synced: root.synced backgroundColor: Theme.color.neutral2 timeTickColor: Theme.color.neutral5 confirmationColors: Theme.color.confirmationColors diff --git a/src/qml/models/nodemodel.cpp b/src/qml/models/nodemodel.cpp index a699376d1a..2ef402067c 100644 --- a/src/qml/models/nodemodel.cpp +++ b/src/qml/models/nodemodel.cpp @@ -20,6 +20,7 @@ NodeModel::NodeModel(interfaces::Node& node) : m_node{node} { ConnectToBlockTipSignal(); + ConnectToHeaderTipSignal(); ConnectToNumConnectionsChangedSignal(); } @@ -31,6 +32,15 @@ void NodeModel::setBlockTipHeight(int new_height) } } + +void NodeModel::setInIBD(bool new_ibd) +{ + if (new_ibd != m_in_ibd) { + m_in_ibd = new_ibd; + Q_EMIT inIBDChanged(); + } +} + void NodeModel::setNumOutboundPeers(int new_num) { if (new_num != m_num_outbound_peers) { @@ -39,6 +49,47 @@ void NodeModel::setNumOutboundPeers(int new_num) } } +void NodeModel::setInHeaderSync(bool new_in_header_sync) +{ + if (new_in_header_sync != m_in_header_sync) { + m_in_header_sync = new_in_header_sync; + Q_EMIT inHeaderSyncChanged(); + } +} + +void NodeModel::setHeaderSyncProgress(int64_t header_height, const QDateTime& block_date) +{ + int estimated_headers_left = block_date.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing; + double new_header_sync_progress = (100.0 / (header_height + estimated_headers_left) * header_height) / 10000; + + if (new_header_sync_progress != m_header_sync_progress) { + m_header_sync_progress = new_header_sync_progress; + setVerificationProgress(0.0); + Q_EMIT headerSyncProgressChanged(); + } +} + +void NodeModel::setInPreHeaderSync(bool new_in_pre_header_sync) +{ + if (new_in_pre_header_sync != m_in_pre_header_sync) { + m_in_pre_header_sync = new_in_pre_header_sync; + Q_EMIT inPreHeaderSyncChanged(); + } +} + +void NodeModel::setPreHeaderSyncProgress(int64_t header_height, const QDateTime& block_date) +{ + int estimated_headers_left = block_date.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing; + double new_pre_header_sync_progress = (100.0 / (header_height + estimated_headers_left) * header_height) / 10000; + + if (new_pre_header_sync_progress != m_pre_header_sync_progress) { + m_pre_header_sync_progress = new_pre_header_sync_progress; + setVerificationProgress(0.0); + Q_EMIT preHeaderSyncProgressChanged(); + + } +} + void NodeModel::setRemainingSyncTime(double new_progress) { int currentTime = QDateTime::currentDateTime().toMSecsSinceEpoch(); @@ -74,12 +125,19 @@ void NodeModel::setRemainingSyncTime(double new_progress) } } } + void NodeModel::setVerificationProgress(double new_progress) { - if (new_progress != m_verification_progress) { - setRemainingSyncTime(new_progress); + double header_progress = m_header_sync_progress + m_pre_header_sync_progress; + if (!m_in_header_sync && !m_in_pre_header_sync) { + if (new_progress != m_verification_progress) { + setRemainingSyncTime(new_progress); - m_verification_progress = new_progress; + m_verification_progress = header_progress + (new_progress - header_progress); + Q_EMIT verificationProgressChanged(); + } + } else { + m_verification_progress = header_progress; Q_EMIT verificationProgressChanged(); } } @@ -139,13 +197,36 @@ void NodeModel::ConnectToBlockTipSignal() [this](SynchronizationState state, interfaces::BlockTip tip, double verification_progress) { QMetaObject::invokeMethod(this, [=] { setBlockTipHeight(tip.block_height); + setInIBD(m_node.isInitialBlockDownload()); setVerificationProgress(verification_progress); - + setInHeaderSync(false); + setInPreHeaderSync(false); Q_EMIT setTimeRatioList(tip.block_time); }); }); } +void NodeModel::ConnectToHeaderTipSignal() +{ + assert(!m_handler_notify_header_tip); + + m_handler_notify_header_tip = m_node.handleNotifyHeaderTip( + [this](SynchronizationState sync_state, interfaces::BlockTip tip, bool presync) { + setInIBD(m_node.isInitialBlockDownload()); + QMetaObject::invokeMethod(this, [=] { + if (presync) { + setInHeaderSync(false); + setInPreHeaderSync(true); + setPreHeaderSyncProgress(tip.block_height, QDateTime::fromSecsSinceEpoch(tip.block_time)); + } else { + setInHeaderSync(true); + setInPreHeaderSync(false); + setHeaderSyncProgress(tip.block_height, QDateTime::fromSecsSinceEpoch(tip.block_time)); + } + }); + }); +} + void NodeModel::ConnectToNumConnectionsChangedSignal() { assert(!m_handler_notify_num_peers_changed); diff --git a/src/qml/models/nodemodel.h b/src/qml/models/nodemodel.h index 442a0becf3..3c7f2b5006 100644 --- a/src/qml/models/nodemodel.h +++ b/src/qml/models/nodemodel.h @@ -28,8 +28,13 @@ class NodeModel : public QObject Q_OBJECT Q_PROPERTY(int blockTipHeight READ blockTipHeight NOTIFY blockTipHeightChanged) Q_PROPERTY(QString fullClientVersion READ fullClientVersion CONSTANT) + Q_PROPERTY(bool inIBD READ inIBD NOTIFY inIBDChanged) Q_PROPERTY(int numOutboundPeers READ numOutboundPeers NOTIFY numOutboundPeersChanged) Q_PROPERTY(int maxNumOutboundPeers READ maxNumOutboundPeers CONSTANT) + Q_PROPERTY(bool inHeaderSync READ inHeaderSync WRITE setInHeaderSync NOTIFY inHeaderSyncChanged) + Q_PROPERTY(double headerSyncProgress READ headerSyncProgress NOTIFY headerSyncProgressChanged) + Q_PROPERTY(bool inPreHeaderSync READ inPreHeaderSync WRITE setInPreHeaderSync NOTIFY inPreHeaderSyncChanged) + Q_PROPERTY(double preHeaderSyncProgress READ preHeaderSyncProgress NOTIFY preHeaderSyncProgressChanged) Q_PROPERTY(int remainingSyncTime READ remainingSyncTime NOTIFY remainingSyncTimeChanged) Q_PROPERTY(double verificationProgress READ verificationProgress NOTIFY verificationProgressChanged) Q_PROPERTY(bool pause READ pause WRITE setPause NOTIFY pauseChanged) @@ -40,9 +45,19 @@ class NodeModel : public QObject int blockTipHeight() const { return m_block_tip_height; } void setBlockTipHeight(int new_height); QString fullClientVersion() const { return QString::fromStdString(FormatFullVersion()); } + bool inIBD() const { return m_in_ibd; } + void setInIBD(bool new_ibd); int numOutboundPeers() const { return m_num_outbound_peers; } void setNumOutboundPeers(int new_num); int maxNumOutboundPeers() const { return m_max_num_outbound_peers; } + bool inHeaderSync() const { return m_in_header_sync; } + void setInHeaderSync(bool new_in_header_sync); + double headerSyncProgress() const { return m_header_sync_progress; } + void setHeaderSyncProgress(int64_t header_height, const QDateTime& block_date); + bool inPreHeaderSync() const { return m_in_pre_header_sync; } + void setInPreHeaderSync(bool new_in_pre_header_sync); + double preHeaderSyncProgress() const { return m_pre_header_sync_progress; } + void setPreHeaderSyncProgress(int64_t header_height, const QDateTime& block_date); int remainingSyncTime() const { return m_remaining_sync_time; } void setRemainingSyncTime(double new_progress); double verificationProgress() const { return m_verification_progress; } @@ -64,7 +79,12 @@ public Q_SLOTS: Q_SIGNALS: void blockTipHeightChanged(); + void inIBDChanged(); void numOutboundPeersChanged(); + void inHeaderSyncChanged(); + void headerSyncProgressChanged(); + void inPreHeaderSyncChanged(); + void preHeaderSyncProgressChanged(); void remainingSyncTimeChanged(); void requestedInitialize(); void requestedShutdown(); @@ -80,8 +100,13 @@ public Q_SLOTS: private: // Properties that are exposed to QML. int m_block_tip_height{0}; + bool m_in_ibd; int m_num_outbound_peers{0}; static constexpr int m_max_num_outbound_peers{MAX_OUTBOUND_FULL_RELAY_CONNECTIONS + MAX_BLOCK_RELAY_ONLY_CONNECTIONS}; + bool m_in_header_sync; + double m_header_sync_progress; + bool m_in_pre_header_sync; + double m_pre_header_sync_progress; int m_remaining_sync_time{0}; double m_verification_progress{0.0}; bool m_pause{false}; @@ -92,9 +117,11 @@ public Q_SLOTS: interfaces::Node& m_node; std::unique_ptr<interfaces::Handler> m_handler_notify_block_tip; + std::unique_ptr<interfaces::Handler> m_handler_notify_header_tip; std::unique_ptr<interfaces::Handler> m_handler_notify_num_peers_changed; void ConnectToBlockTipSignal(); + void ConnectToHeaderTipSignal(); void ConnectToNumConnectionsChangedSignal(); };