aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/node.cpp9
-rw-r--r--src/interfaces/node.h7
-rw-r--r--src/interfaces/wallet.cpp4
-rw-r--r--src/interfaces/wallet.h2
-rw-r--r--src/qt/clientmodel.cpp16
-rw-r--r--src/qt/clientmodel.h6
-rw-r--r--src/qt/transactionrecord.cpp8
-rw-r--r--src/qt/transactionrecord.h13
-rw-r--r--src/qt/transactiontablemodel.cpp8
-rw-r--r--src/qt/walletmodel.cpp12
-rw-r--r--src/qt/walletmodel.h6
11 files changed, 57 insertions, 34 deletions
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 3c94e44b53..582bf68ff8 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -187,6 +187,11 @@ public:
LOCK(::cs_main);
return ::ChainActive().Height();
}
+ uint256 getBestBlockHash() override
+ {
+ const CBlockIndex* tip = WITH_LOCK(::cs_main, return ::ChainActive().Tip());
+ return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash();
+ }
int64_t getLastBlockTime() override
{
LOCK(::cs_main);
@@ -310,7 +315,7 @@ public:
std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override
{
return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
- fn(sync_state, block->nHeight, block->GetBlockTime(),
+ fn(sync_state, block->GetBlockHash(), block->nHeight, block->GetBlockTime(),
GuessVerificationProgress(Params().TxData(), block));
}));
}
@@ -318,7 +323,7 @@ public:
{
return MakeHandler(
::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
- fn(sync_state, block->nHeight, block->GetBlockTime(),
+ fn(sync_state, block->GetBlockHash(), block->nHeight, block->GetBlockTime(),
/* verification progress is unused when a header was received */ 0);
}));
}
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 45b0e18fae..e4df908847 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -149,6 +149,9 @@ public:
//! Get num blocks.
virtual int getNumBlocks() = 0;
+ //! Get best block hash.
+ virtual uint256 getBestBlockHash() = 0;
+
//! Get last block time.
virtual int64_t getLastBlockTime() = 0;
@@ -250,12 +253,12 @@ public:
//! Register handler for block tip messages.
using NotifyBlockTipFn =
- std::function<void(SynchronizationState, int height, int64_t block_time, double verification_progress)>;
+ std::function<void(SynchronizationState, const uint256& block_hash, int height, int64_t block_time, double verification_progress)>;
virtual std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) = 0;
//! Register handler for header tip messages.
using NotifyHeaderTipFn =
- std::function<void(SynchronizationState, int height, int64_t block_time, double verification_progress)>;
+ std::function<void(SynchronizationState, const uint256& block_hash, int height, int64_t block_time, double verification_progress)>;
virtual std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) = 0;
//! Return pointer to internal chain interface, useful for testing.
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 349dce0247..cec75030ad 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -351,13 +351,13 @@ public:
}
return result;
}
- bool tryGetBalances(WalletBalances& balances, int& num_blocks) override
+ bool tryGetBalances(WalletBalances& balances, uint256& block_hash) override
{
TRY_LOCK(m_wallet->cs_wallet, locked_wallet);
if (!locked_wallet) {
return false;
}
- num_blocks = m_wallet->GetLastBlockHeight();
+ block_hash = m_wallet->GetLastBlockHash();
balances = getBalances();
return true;
}
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index 421d35af15..67569a3e55 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -203,7 +203,7 @@ public:
virtual WalletBalances getBalances() = 0;
//! Get balances if possible without blocking.
- virtual bool tryGetBalances(WalletBalances& balances, int& num_blocks) = 0;
+ virtual bool tryGetBalances(WalletBalances& balances, uint256& block_hash) = 0;
//! Get balance.
virtual CAmount getBalance() = 0;
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 <atomic>
#include <memory>
+#include <sync.h>
+#include <uint256.h>
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<int64_t> cachedBestHeaderTime;
mutable std::atomic<int> 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<interfaces::Handler> 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> 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<interfaces::Wallet> 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);