diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 5caf65e2a216c..1c0e948c5de70 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -205,24 +205,26 @@ static bool processBalanceChangeInternal(WalletModel* walletModel) int chainHeight = walletModel->getLastBlockProcessedNum(); const uint256& blockHash = walletModel->getLastBlockProcessed(); - if (walletModel->hasForceCheckBalance() || chainHeight != walletModel->getCacheNumBLocks()) { - // Try to get lock only if needed - TRY_LOCK(pwalletMain->cs_wallet, lockWallet); - if (!lockWallet) - return false; - - walletModel->setfForceCheckBalanceChanged(false); - - // Balance and number of transactions might have changed - walletModel->setCacheNumBlocks(chainHeight); - walletModel->setCacheBlockHash(blockHash); - walletModel->checkBalanceChanged(walletModel->getBalances()); - QMetaObject::invokeMethod(walletModel, "updateTxModelData", Qt::QueuedConnection); - QMetaObject::invokeMethod(walletModel, "pollFinished", Qt::QueuedConnection); - - // Address in receive tab may have been used - Q_EMIT walletModel->notifyReceiveAddressChanged(); - } + // Avoid recomputing wallet balances unless a tx changed or BlockTip notification was received. + // Extra note: This needs to be done before and after the update task trigger and execution because, as it runs concurrently, + // there is no guarantee that the threadpool will execute the task right away. + if (!walletModel->hasForceCheckBalance() && walletModel->getCacheBlockHash() == blockHash) return false; + + // Try to get lock only if needed + TRY_LOCK(pwalletMain->cs_wallet, lockWallet); + if (!lockWallet) return false; + + walletModel->setfForceCheckBalanceChanged(false); + + // Balance and number of transactions might have changed + walletModel->setCacheNumBlocks(chainHeight); + walletModel->setCacheBlockHash(blockHash); + walletModel->checkBalanceChanged(walletModel->getBalances()); + QMetaObject::invokeMethod(walletModel, "updateTxModelData", Qt::QueuedConnection); + QMetaObject::invokeMethod(walletModel, "pollFinished", Qt::QueuedConnection); + + // Address in receive tab may have been used + Q_EMIT walletModel->notifyReceiveAddressChanged(); return true; } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index ce0ffb91c61a3..204b1cd0a9ffa 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -340,6 +340,7 @@ class WalletModel : public QObject void setCacheNumBlocks(int _cachedNumBlocks) { cachedNumBlocks = _cachedNumBlocks; } int getCacheNumBLocks() { return cachedNumBlocks; } void setCacheBlockHash(const uint256& _blockHash) { m_cached_best_block_hash = _blockHash; } + uint256 getCacheBlockHash() { return m_cached_best_block_hash; } void setfForceCheckBalanceChanged(bool _fForceCheckBalanceChanged) { fForceCheckBalanceChanged = _fForceCheckBalanceChanged; } Q_INVOKABLE void checkBalanceChanged(const interfaces::WalletBalances& new_balances);