Skip to content

Commit 22c2b63

Browse files
hebastoclaude
authored andcommitted
Merge bitcoin-core/gui#598: Avoid recalculating the wallet balance - use model cache
4584d30 GUI: remove now unneeded 'm_balances' field from overviewpage (furszy) 050e8b1 GUI: 'getAvailableBalance', use cached balance if the user did not select UTXO manually (furszy) 96e3264 GUI: use cached balance in overviewpage and sendcoinsdialog (furszy) 321335b GUI: add getter for WalletModel::m_cached_balances field (furszy) e62958d GUI: sendCoinsDialog, remove duplicate wallet().getBalances() call (furszy)
1 parent 35c7990 commit 22c2b63

7 files changed

Lines changed: 49 additions & 28 deletions

File tree

‎src/qt/overviewpage.cpp‎

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,6 @@ OverviewPage::OverviewPage(QWidget* parent) :
168168

169169
GUIUtil::updateFonts();
170170

171-
m_balances.balance = -1;
172-
173171
// Recent transactions
174172
ui->listTransactions->setItemDelegate(txdelegate);
175173
// Note: minimum height of listTransactions will be set later in updateAdvancedCJUI() to reflect actual settings
@@ -206,8 +204,9 @@ void OverviewPage::handleTransactionClicked(const QModelIndex &index)
206204
void OverviewPage::setPrivacy(bool privacy)
207205
{
208206
m_privacy = privacy;
209-
if (m_balances.balance != -1) {
210-
setBalance(m_balances);
207+
const auto& balances = walletModel->getCachedBalance();
208+
if (balances.balance != -1) {
209+
setBalance(balances);
211210
coinJoinStatus(true);
212211
}
213212

@@ -230,7 +229,6 @@ OverviewPage::~OverviewPage()
230229
void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
231230
{
232231
BitcoinUnit unit = walletModel->getOptionsModel()->getDisplayUnit();
233-
m_balances = balances;
234232
if (walletModel->wallet().isLegacy()) {
235233
if (walletModel->wallet().privateKeysDisabled()) {
236234
ui->labelBalance->setText(BitcoinUnits::floorHtmlWithPrivacy(unit, balances.watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
@@ -316,14 +314,13 @@ void OverviewPage::setWalletModel(WalletModel *model)
316314
// update the display unit, to not use the default ("DASH")
317315
updateDisplayUnit();
318316
// Keep up to date with wallet
319-
interfaces::Wallet& wallet = model->wallet();
320-
interfaces::WalletBalances balances = wallet.getBalances();
321-
setBalance(balances);
317+
setBalance(model->getCachedBalance());
322318
connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance);
323319

324320
connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit);
325321

326-
updateWatchOnlyLabels((wallet.haveWatchOnly() && !model->wallet().privateKeysDisabled()) || gArgs.GetBoolArg("-debug-ui", false));
322+
interfaces::Wallet& wallet = model->wallet();
323+
updateWatchOnlyLabels((wallet.haveWatchOnly() && !wallet.privateKeysDisabled()) || gArgs.GetBoolArg("-debug-ui", false));
327324
connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
328325
updateWatchOnlyLabels(showWatchOnly && !walletModel->wallet().privateKeysDisabled());
329326
});
@@ -348,11 +345,11 @@ void OverviewPage::setWalletModel(WalletModel *model)
348345

349346
void OverviewPage::updateDisplayUnit()
350347
{
351-
if(walletModel && walletModel->getOptionsModel())
352-
{
348+
if (walletModel && walletModel->getOptionsModel()) {
353349
m_display_bitcoin_unit = walletModel->getOptionsModel()->getDisplayUnit();
354-
if (m_balances.balance != -1) {
355-
setBalance(m_balances);
350+
const auto& balances = walletModel->getCachedBalance();
351+
if (balances.balance != -1) {
352+
setBalance(balances);
356353
}
357354

358355
// Update txdelegate->unit with the current unit
@@ -379,10 +376,11 @@ void OverviewPage::updateCoinJoinProgress()
379376
{
380377
if (!walletModel || !clientModel || clientModel->node().shutdownRequested() || !clientModel->masternodeSync().isBlockchainSynced()) return;
381378

379+
const auto& cached_balances = walletModel->getCachedBalance();
382380
QString strAmountAndRounds;
383381
QString strCoinJoinAmount = BitcoinUnits::formatHtmlWithUnit(m_display_bitcoin_unit, clientModel->coinJoinOptions().getAmount() * COIN, false, BitcoinUnits::SeparatorStyle::ALWAYS);
384382

385-
if(m_balances.balance == 0)
383+
if (cached_balances.balance == 0)
386384
{
387385
ui->coinJoinProgress->setValue(0);
388386
ui->coinJoinProgress->setToolTip(tr("No inputs detected"));
@@ -398,7 +396,7 @@ void OverviewPage::updateCoinJoinProgress()
398396

399397
CAmount nAnonymizableBalance = walletModel->wallet().getAnonymizableBalance(false, false);
400398

401-
CAmount nMaxToAnonymize = nAnonymizableBalance + m_balances.anonymized_balance;
399+
CAmount nMaxToAnonymize = nAnonymizableBalance + cached_balances.anonymized_balance;
402400

403401
// If it's more than the anon threshold, limit to that.
404402
if (nMaxToAnonymize > clientModel->coinJoinOptions().getAmount() * COIN) nMaxToAnonymize = clientModel->coinJoinOptions().getAmount() * COIN;
@@ -455,7 +453,7 @@ void OverviewPage::updateCoinJoinProgress()
455453
anonNormPart = anonNormPart > 1 ? 1 : anonNormPart;
456454
anonNormPart *= 100;
457455

458-
anonFullPart = (float)m_balances.anonymized_balance / nMaxToAnonymize;
456+
anonFullPart = (float)cached_balances.anonymized_balance / nMaxToAnonymize;
459457
anonFullPart = anonFullPart > 1 ? 1 : anonFullPart;
460458
anonFullPart *= 100;
461459

@@ -683,7 +681,7 @@ void OverviewPage::toggleCoinJoin(){
683681
if (!walletModel->coinJoin()->isMixing()) {
684682
auto& options = walletModel->node().coinJoinOptions();
685683
const CAmount nMinAmount = options.getSmallestDenomination() + options.getMaxCollateralAmount();
686-
if(m_balances.balance < nMinAmount) {
684+
if (walletModel->getCachedBalance().balance < nMinAmount) {
687685
QString strMinAmount(BitcoinUnits::formatWithUnit(m_display_bitcoin_unit, nMinAmount));
688686
QMessageBox::warning(this, strCoinJoinName,
689687
tr("%1 requires at least %2 to use.").arg(strCoinJoinName).arg(strMinAmount),

‎src/qt/overviewpage.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ public Q_SLOTS:
5151
Ui::OverviewPage *ui;
5252
ClientModel *clientModel;
5353
WalletModel *walletModel;
54-
interfaces::WalletBalances m_balances;
5554
bool m_privacy{false};
5655
BitcoinUnit m_display_bitcoin_unit;
5756
bool fShowAdvancedCJUI;

‎src/qt/sendcoinsdialog.cpp‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,9 @@ void SendCoinsDialog::setModel(WalletModel *_model)
180180
}
181181
}
182182

183-
interfaces::WalletBalances balances = _model->wallet().getBalances();
184-
setBalance(balances);
185183
connect(_model, &WalletModel::balanceChanged, this, &SendCoinsDialog::setBalance);
186-
connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::updateDisplayUnit);
187-
updateDisplayUnit();
184+
connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::refreshBalance);
185+
refreshBalance();
188186

189187
// Coin Control
190188
connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
@@ -782,9 +780,9 @@ void SendCoinsDialog::setBalance(const interfaces::WalletBalances& balances)
782780
}
783781
}
784782

785-
void SendCoinsDialog::updateDisplayUnit()
783+
void SendCoinsDialog::refreshBalance()
786784
{
787-
setBalance(model->wallet().getBalances());
785+
setBalance(model->getCachedBalance());
788786
coinControlUpdateLabels();
789787
ui->customFee->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
790788
updateSmartFeeLabel();
@@ -858,7 +856,7 @@ void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry)
858856
m_coin_control->fAllowWatchOnly = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner();
859857

860858
// Calculate available amount to send.
861-
CAmount amount = model->wallet().getAvailableBalance(*m_coin_control);
859+
CAmount amount = model->getAvailableBalance(m_coin_control.get());
862860
for (int i = 0; i < ui->entries->count(); ++i) {
863861
SendCoinsEntry* e = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
864862
if (e && !e->isHidden() && e != entry) {

‎src/qt/sendcoinsdialog.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ private Q_SLOTS:
8888
void on_buttonMinimizeFee_clicked();
8989
void removeEntry(SendCoinsEntry* entry);
9090
void useAvailableBalance(SendCoinsEntry* entry);
91-
void updateDisplayUnit();
91+
void refreshBalance();
9292
void coinControlFeatureChanged(bool);
9393
void coinControlButtonClicked();
9494
void coinControlChangeChecked(int);

‎src/qt/test/wallettests.cpp‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ void TestGUI(interfaces::Node& node)
159159
sendCoinsDialog.setModel(&walletModel);
160160
transactionView.setModel(&walletModel);
161161

162+
// Update walletModel cached balance which will trigger an update for the 'labelBalance' QLabel.
163+
walletModel.pollBalanceChanged();
162164
{
163165
// Check balance in send dialog
164166
QLabel* balanceLabel = sendCoinsDialog.findChild<QLabel*>("labelBalance");
@@ -184,6 +186,7 @@ void TestGUI(interfaces::Node& node)
184186
OverviewPage overviewPage;
185187
overviewPage.setClientModel(&clientModel);
186188
overviewPage.setWalletModel(&walletModel);
189+
walletModel.pollBalanceChanged(); // Manual balance polling update
187190
QLabel* balanceLabel = overviewPage.findChild<QLabel*>("labelBalance");
188191
QString balanceText = balanceLabel->text().trimmed();
189192
BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit();

‎src/qt/walletmodel.cpp‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ WalletModel::~WalletModel()
7373

7474
void WalletModel::startPollBalance()
7575
{
76+
// Update the cached balance right away, so every view can make use of it,
77+
// so them don't need to waste resources recalculating it.
78+
pollBalanceChanged();
79+
7680
// This timer will be fired repeatedly to update the balance
7781
// Since the QTimer::timeout is a private signal, it cannot be used
7882
// in the GUIUtil::ExceptionSafeConnect directly.
@@ -137,12 +141,17 @@ void WalletModel::pollBalanceChanged()
137141

138142
void WalletModel::checkBalanceChanged(const interfaces::WalletBalances& new_balances)
139143
{
140-
if(new_balances.balanceChanged(m_cached_balances)) {
144+
if (new_balances.balanceChanged(m_cached_balances)) {
141145
m_cached_balances = new_balances;
142146
Q_EMIT balanceChanged(new_balances);
143147
}
144148
}
145149

150+
interfaces::WalletBalances WalletModel::getCachedBalance() const
151+
{
152+
return m_cached_balances;
153+
}
154+
146155
void WalletModel::updateTransaction()
147156
{
148157
// Balance and number of transactions might have changed
@@ -244,7 +253,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
244253
return DuplicateAddress;
245254
}
246255

247-
CAmount nBalance = m_wallet->getAvailableBalance(coinControl);
256+
// If no coin was manually selected, use the cached balance
257+
// Future: can merge this call with 'createTransaction'.
258+
CAmount nBalance = getAvailableBalance(&coinControl);
248259

249260
if(total > nBalance)
250261
{
@@ -616,3 +627,8 @@ uint256 WalletModel::getLastBlockProcessed() const
616627
{
617628
return m_client_model ? m_client_model->getBestBlockHash() : uint256{};
618629
}
630+
631+
CAmount WalletModel::getAvailableBalance(const CCoinControl* control)
632+
{
633+
return control && control->HasSelected() ? wallet().getAvailableBalance(*control) : getCachedBalance().balance;
634+
}

‎src/qt/walletmodel.h‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,13 @@ class WalletModel : public QObject
162162

163163
uint256 getLastBlockProcessed() const;
164164

165+
// Retrieve the cached wallet balance
166+
interfaces::WalletBalances getCachedBalance() const;
167+
168+
// If coin control has selected outputs, searches the total amount inside the wallet.
169+
// Otherwise, uses the wallet's cached available balance.
170+
CAmount getAvailableBalance(const wallet::CCoinControl* control);
171+
165172
private:
166173
std::unique_ptr<interfaces::Wallet> m_wallet;
167174
std::unique_ptr<interfaces::Handler> m_handler_unload;

0 commit comments

Comments
 (0)