From 2f867203b0c7a4438ce484be4cfa2b29dbf1abf0 Mon Sep 17 00:00:00 2001 From: furszy Date: Thu, 23 Jan 2020 19:31:16 -0300 Subject: Added best block hash to the NotifyHeaderTip and NotifyBlockTip signals. [ClientModel] best header/block hash cached. --- src/qt/clientmodel.cpp | 16 +++++++++++++--- src/qt/clientmodel.h | 6 ++++++ src/qt/transactionrecord.cpp | 8 ++++---- src/qt/transactionrecord.h | 13 ++++++------- src/qt/transactiontablemodel.cpp | 8 ++++---- src/qt/walletmodel.cpp | 12 +++++------- src/qt/walletmodel.h | 6 ++++-- 7 files changed, 42 insertions(+), 27 deletions(-) (limited to 'src/qt') diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 159b0d3df3..3ef044d6f8 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -114,6 +114,15 @@ int ClientModel::getNumBlocks() const return m_cached_num_blocks; } +uint256 ClientModel::getBestBlockHash() +{ + LOCK(m_cached_tip_mutex); + if (m_cached_tip_blocks.IsNull()) { + m_cached_tip_blocks = m_node.getBestBlockHash(); + } + return m_cached_tip_blocks; +} + void ClientModel::updateNumConnections(int numConnections) { Q_EMIT numConnectionsChanged(numConnections); @@ -235,7 +244,7 @@ static void BannedListChanged(ClientModel *clientmodel) assert(invoked); } -static void BlockTipChanged(ClientModel* clientmodel, SynchronizationState sync_state, int height, int64_t blockTime, double verificationProgress, bool fHeader) +static void BlockTipChanged(ClientModel* clientmodel, SynchronizationState sync_state, const uint256 block_hash, int height, int64_t blockTime, double verificationProgress, bool fHeader) { if (fHeader) { // cache best headers time and height to reduce future cs_main locks @@ -243,6 +252,7 @@ static void BlockTipChanged(ClientModel* clientmodel, SynchronizationState sync_ clientmodel->cachedBestHeaderTime = blockTime; } else { clientmodel->m_cached_num_blocks = height; + WITH_LOCK(clientmodel->m_cached_tip_mutex, clientmodel->m_cached_tip_blocks = block_hash;); } // Throttle GUI notifications about (a) blocks during initial sync, and (b) both blocks and headers during reindex. @@ -271,8 +281,8 @@ void ClientModel::subscribeToCoreSignals() m_handler_notify_network_active_changed = m_node.handleNotifyNetworkActiveChanged(std::bind(NotifyNetworkActiveChanged, this, std::placeholders::_1)); m_handler_notify_alert_changed = m_node.handleNotifyAlertChanged(std::bind(NotifyAlertChanged, this)); m_handler_banned_list_changed = m_node.handleBannedListChanged(std::bind(BannedListChanged, this)); - m_handler_notify_block_tip = m_node.handleNotifyBlockTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, false)); - m_handler_notify_header_tip = m_node.handleNotifyHeaderTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, true)); + m_handler_notify_block_tip = m_node.handleNotifyBlockTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, false)); + m_handler_notify_header_tip = m_node.handleNotifyHeaderTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, true)); } void ClientModel::unsubscribeFromCoreSignals() diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index ace77f5972..aa324bc9ea 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -10,6 +10,8 @@ #include #include +#include +#include class BanTableModel; class CBlockIndex; @@ -57,6 +59,7 @@ public: //! Return number of connections, default is in- and outbound (total) int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; int getNumBlocks() const; + uint256 getBestBlockHash(); int getHeaderTipHeight() const; int64_t getHeaderTipTime() const; @@ -79,6 +82,9 @@ public: mutable std::atomic cachedBestHeaderTime; mutable std::atomic m_cached_num_blocks{-1}; + Mutex m_cached_tip_mutex; + uint256 m_cached_tip_blocks GUARDED_BY(m_cached_tip_mutex){}; + private: interfaces::Node& m_node; std::unique_ptr m_handler_show_progress; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index a32d218fc9..01dff8069c 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -162,7 +162,7 @@ QList TransactionRecord::decomposeTransaction(const interface return parts; } -void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t block_time) +void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, const uint256& block_hash, int numBlocks, int64_t block_time) { // Determine transaction status @@ -174,7 +174,7 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int idx); status.countsForBalance = wtx.is_trusted && !(wtx.blocks_to_maturity > 0); status.depth = wtx.depth_in_main_chain; - status.cur_num_blocks = numBlocks; + status.m_cur_block_hash = block_hash; const bool up_to_date = ((int64_t)QDateTime::currentMSecsSinceEpoch() / 1000 - block_time < MAX_BLOCK_TIME_GAP); if (up_to_date && !wtx.is_final) { @@ -233,9 +233,9 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int status.needsUpdate = false; } -bool TransactionRecord::statusUpdateNeeded(int numBlocks) const +bool TransactionRecord::statusUpdateNeeded(const uint256& block_hash) const { - return status.cur_num_blocks != numBlocks || status.needsUpdate; + return status.m_cur_block_hash != block_hash || status.needsUpdate; } QString TransactionRecord::getTxHash() const diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 3f64cefd09..c983c527c0 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -23,9 +23,8 @@ struct WalletTxStatus; class TransactionStatus { public: - TransactionStatus(): - countsForBalance(false), sortKey(""), - matures_in(0), status(Unconfirmed), depth(0), open_for(0), cur_num_blocks(-1) + TransactionStatus() : countsForBalance(false), sortKey(""), + matures_in(0), status(Unconfirmed), depth(0), open_for(0) { } enum Status { @@ -61,8 +60,8 @@ public: finalization */ /**@}*/ - /** Current number of blocks (to know whether cached status is still valid) */ - int cur_num_blocks; + /** Current block hash (to know whether cached status is still valid) */ + uint256 m_cur_block_hash{}; bool needsUpdate; }; @@ -138,11 +137,11 @@ public: /** Update status from core wallet tx. */ - void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t block_time); + void updateStatus(const interfaces::WalletTxStatus& wtx, const uint256& block_hash, int numBlocks, int64_t block_time); /** Return whether a status update is needed. */ - bool statusUpdateNeeded(int numBlocks) const; + bool statusUpdateNeeded(const uint256& block_hash) const; }; #endif // BITCOIN_QT_TRANSACTIONRECORD_H diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 7a15503228..0867ae8105 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -176,7 +176,7 @@ public: return cachedWallet.size(); } - TransactionRecord *index(interfaces::Wallet& wallet, const int cur_num_blocks, const int idx) + TransactionRecord* index(interfaces::Wallet& wallet, const uint256& cur_block_hash, const int idx) { if(idx >= 0 && idx < cachedWallet.size()) { @@ -192,8 +192,8 @@ public: interfaces::WalletTxStatus wtx; int numBlocks; int64_t block_time; - if (rec->statusUpdateNeeded(cur_num_blocks) && wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time)) { - rec->updateStatus(wtx, numBlocks, block_time); + if (rec->statusUpdateNeeded(cur_block_hash) && wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time)) { + rec->updateStatus(wtx, cur_block_hash, numBlocks, block_time); } return rec; } @@ -664,7 +664,7 @@ QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientat QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const { Q_UNUSED(parent); - TransactionRecord *data = priv->index(walletModel->wallet(), walletModel->getNumBlocks(), row); + TransactionRecord* data = priv->index(walletModel->wallet(), walletModel->clientModel().getBestBlockHash(), row); if(data) { return createIndex(row, column, data); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 1084ec9725..386002eaf2 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -46,7 +46,6 @@ WalletModel::WalletModel(std::unique_ptr wallet, ClientModel transactionTableModel(nullptr), recentRequestsTableModel(nullptr), cachedEncryptionStatus(Unencrypted), - cachedNumBlocks(0), timer(new QTimer(this)) { fHaveWatchOnly = m_wallet->haveWatchOnly(); @@ -88,24 +87,23 @@ void WalletModel::pollBalanceChanged() { // Avoid recomputing wallet balances unless a TransactionChanged or // BlockTip notification was received. - if (!fForceCheckBalanceChanged && cachedNumBlocks == m_client_model->getNumBlocks()) return; + if (!fForceCheckBalanceChanged && m_cached_last_update_tip == m_client_model->getBestBlockHash()) return; // Try to get balances and return early if locks can't be acquired. This // avoids the GUI from getting stuck on periodical polls if the core is // holding the locks for a longer time - for example, during a wallet // rescan. interfaces::WalletBalances new_balances; - int numBlocks = -1; - if (!m_wallet->tryGetBalances(new_balances, numBlocks)) { + uint256 block_hash; + if (!m_wallet->tryGetBalances(new_balances, block_hash)) { return; } - if(fForceCheckBalanceChanged || numBlocks != cachedNumBlocks) - { + if (fForceCheckBalanceChanged || block_hash != m_cached_last_update_tip) { fForceCheckBalanceChanged = false; // Balance and number of transactions might have changed - cachedNumBlocks = numBlocks; + m_cached_last_update_tip = block_hash; checkBalanceChanged(new_balances); if(transactionTableModel) diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 23232ec66b..59470c002d 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -144,8 +144,8 @@ public: interfaces::Node& node() const { return m_node; } interfaces::Wallet& wallet() const { return *m_wallet; } + ClientModel& clientModel() const { return *m_client_model; } void setClientModel(ClientModel* client_model); - int getNumBlocks() const { return cachedNumBlocks; } QString getWalletName() const; QString getDisplayName() const; @@ -179,9 +179,11 @@ private: // Cache some values to be able to detect changes interfaces::WalletBalances m_cached_balances; EncryptionStatus cachedEncryptionStatus; - int cachedNumBlocks; QTimer* timer; + // Block hash denoting when the last balance update was done. + uint256 m_cached_last_update_tip{}; + void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); void checkBalanceChanged(const interfaces::WalletBalances& new_balances); -- cgit v1.2.3