From 8df54fe3557a6e7d1d027b986d377f53fdb3b30d Mon Sep 17 00:00:00 2001 From: jarolrod Date: Tue, 28 Feb 2023 02:34:16 -0500 Subject: [PATCH 1/2] qml: handle pre & header sync, move verification progress along This connects us to the header tip signal so that we can handle when the node is in pre & or headers sync. This calculates the progress of the pre or headers sync and adds it to our verification progress. Pre and headers sync take up 1% of verification progress each, then IBD begins at 2% progress as displayed on the block clock. --- src/qml/models/nodemodel.cpp | 78 ++++++++++++++++++++++++++++++++++-- src/qml/models/nodemodel.h | 22 ++++++++++ 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/src/qml/models/nodemodel.cpp b/src/qml/models/nodemodel.cpp index a699376d1a..1bf1049f91 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(); } @@ -39,6 +40,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 +116,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(); } } @@ -140,12 +189,33 @@ void NodeModel::ConnectToBlockTipSignal() QMetaObject::invokeMethod(this, [=] { setBlockTipHeight(tip.block_height); 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) { + 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..dc63156e2a 100644 --- a/src/qml/models/nodemodel.h +++ b/src/qml/models/nodemodel.h @@ -30,6 +30,10 @@ class NodeModel : public QObject Q_PROPERTY(QString fullClientVersion READ fullClientVersion CONSTANT) 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) @@ -43,6 +47,14 @@ class NodeModel : public QObject 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; } @@ -65,6 +77,10 @@ public Q_SLOTS: Q_SIGNALS: void blockTipHeightChanged(); void numOutboundPeersChanged(); + void inHeaderSyncChanged(); + void headerSyncProgressChanged(); + void inPreHeaderSyncChanged(); + void preHeaderSyncProgressChanged(); void remainingSyncTimeChanged(); void requestedInitialize(); void requestedShutdown(); @@ -82,6 +98,10 @@ public Q_SLOTS: int m_block_tip_height{0}; 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 +112,11 @@ public Q_SLOTS: interfaces::Node& m_node; std::unique_ptr m_handler_notify_block_tip; + std::unique_ptr m_handler_notify_header_tip; std::unique_ptr m_handler_notify_num_peers_changed; void ConnectToBlockTipSignal(); + void ConnectToHeaderTipSignal(); void ConnectToNumConnectionsChangedSignal(); }; From f6bb1b1c39bb87940846eba65408025fabc672f3 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 28 Feb 2023 23:40:43 -0500 Subject: [PATCH 2/2] qml: set synced to whether node is in IBD or not This changes when we consider to be synced within the block clock's perspective from a check on if verificationProgress is large enough to a query on the node to see if it is in ibd or not --- src/qml/components/BlockClock.qml | 4 ++-- src/qml/models/nodemodel.cpp | 11 +++++++++++ src/qml/models/nodemodel.h | 5 +++++ 3 files changed, 18 insertions(+), 2 deletions(-) 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 1bf1049f91..2ef402067c 100644 --- a/src/qml/models/nodemodel.cpp +++ b/src/qml/models/nodemodel.cpp @@ -32,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) { @@ -188,6 +197,7 @@ 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); @@ -202,6 +212,7 @@ void NodeModel::ConnectToHeaderTipSignal() 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); diff --git a/src/qml/models/nodemodel.h b/src/qml/models/nodemodel.h index dc63156e2a..3c7f2b5006 100644 --- a/src/qml/models/nodemodel.h +++ b/src/qml/models/nodemodel.h @@ -28,6 +28,7 @@ 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) @@ -44,6 +45,8 @@ 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; } @@ -76,6 +79,7 @@ public Q_SLOTS: Q_SIGNALS: void blockTipHeightChanged(); + void inIBDChanged(); void numOutboundPeersChanged(); void inHeaderSyncChanged(); void headerSyncProgressChanged(); @@ -96,6 +100,7 @@ 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;