-
Notifications
You must be signed in to change notification settings - Fork 1.2k
backport: bitcoin#25933, bitcoin-core/gui#598, partial #26699 #7602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
87e5be4
01c5701
2c5fa19
b8c7d4a
5b34dab
0d69256
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,6 +63,9 @@ WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, ClientModel | |
| connect(optionsModel, &OptionsModel::dustProtectionChanged, this, &WalletModel::lockExistingDustOutputs); | ||
| // Lock existing dust on startup if dust protection is enabled | ||
| lockExistingDustOutputs(); | ||
| // CoinJoin balances are calculated only while CoinJoin is enabled, | ||
| // so the cached balance must be recalculated when it is toggled | ||
| connect(optionsModel, &OptionsModel::showCoinJoinChanged, this, [this] { fForceCheckBalanceChanged = true; }); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -73,6 +76,10 @@ WalletModel::~WalletModel() | |
|
|
||
| void WalletModel::startPollBalance() | ||
| { | ||
| // Update the cached balance right away, so every view can make use of it, | ||
| // so them don't need to waste resources recalculating it. | ||
| pollBalanceChanged(); | ||
|
|
||
| // This timer will be fired repeatedly to update the balance | ||
| // Since the QTimer::timeout is a private signal, it cannot be used | ||
| // in the GUIUtil::ExceptionSafeConnect directly. | ||
|
|
@@ -137,12 +144,17 @@ void WalletModel::pollBalanceChanged() | |
|
|
||
| void WalletModel::checkBalanceChanged(const interfaces::WalletBalances& new_balances) | ||
| { | ||
| if(new_balances.balanceChanged(m_cached_balances)) { | ||
| if (new_balances.balanceChanged(m_cached_balances)) { | ||
| m_cached_balances = new_balances; | ||
| Q_EMIT balanceChanged(new_balances); | ||
| } | ||
| } | ||
|
|
||
| interfaces::WalletBalances WalletModel::getCachedBalance() const | ||
| { | ||
| return m_cached_balances; | ||
| } | ||
|
|
||
| void WalletModel::updateTransaction() | ||
| { | ||
| // Balance and number of transactions might have changed | ||
|
|
@@ -258,7 +270,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact | |
| } | ||
| } | ||
|
|
||
| CAmount nBalance = m_wallet->getAvailableBalance(coinControl); | ||
| // If no coin was manually selected, use the cached balance | ||
| // Future: can merge this call with 'createTransaction'. | ||
| CAmount nBalance = getAvailableBalance(&coinControl); | ||
|
|
||
| if(total > nBalance) | ||
| { | ||
|
|
@@ -633,3 +647,25 @@ uint256 WalletModel::getLastBlockProcessed() const | |
| { | ||
| return m_client_model ? m_client_model->getBestBlockHash() : uint256{}; | ||
| } | ||
|
|
||
| CAmount WalletModel::getAvailableBalance(const CCoinControl* control) | ||
| { | ||
| // No selected coins, return the cached balance | ||
| if (!control || !control->HasSelected()) { | ||
| const interfaces::WalletBalances& balances = getCachedBalance(); | ||
| if (control && control->IsUsingCoinJoin()) { | ||
| return balances.anonymized_balance; | ||
|
Comment on lines
+656
to
+657
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When CoinJoin is disabled during the initial balance poll, Useful? React with 👍 / 👎.
Comment on lines
+656
to
+657
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Blocking: Refresh the balance cache when CoinJoin is enabled When CoinJoin is disabled, source: ['codex'] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolved in this update — Refresh the balance cache when CoinJoin is enabled no longer present. Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread. |
||
| } | ||
| // The cached balance counts locked coins, which coin selection cannot | ||
| // spend; exclude their live total, as lock changes don't trigger a repoll | ||
| CAmount available_balance = balances.balance - m_wallet->getLockedBalance(); | ||
|
Comment on lines
+655
to
+661
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an Useful? React with 👍 / 👎.
Comment on lines
+655
to
+661
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Blocking: Honor coin control's address-reuse policy For a wallet with source: ['codex'] |
||
| // if wallet private keys are disabled, this is a watch-only wallet | ||
| // so, let's include the watch-only balance. | ||
| if (balances.have_watch_only && m_wallet->privateKeysDisabled()) { | ||
| available_balance += balances.watch_only_balance; | ||
| } | ||
| return available_balance; | ||
| } | ||
| // Fetch balance from the wallet, taking into account the selected coins | ||
| return wallet().getAvailableBalance(*control); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -331,6 +331,25 @@ Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse, | |
| return ret; | ||
| } | ||
|
|
||
| CAmount GetLockedBalance(const CWallet& wallet) | ||
| { | ||
| CAmount total{0}; | ||
| LOCK(wallet.cs_wallet); | ||
| std::set<uint256> trusted_parents; | ||
| for (const COutPoint& outpoint : wallet.ListLockedCoins()) { | ||
| const CWalletTx* wtx = wallet.GetWalletTx(outpoint.hash); | ||
| if (!wtx || outpoint.n >= wtx->tx->vout.size()) continue; | ||
| // Mirror the conditions under which GetBalance() counts an output | ||
| // towards m_mine_trusted | ||
| if (wallet.IsSpent(outpoint) || wallet.IsTxImmatureCoinBase(*wtx)) continue; | ||
| if (!CachedTxIsTrusted(wallet, *wtx, trusted_parents)) continue; | ||
| const CTxOut& txout{wtx->tx->vout[outpoint.n]}; | ||
| if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE) && wallet.IsSpentKey(txout.scriptPubKey)) continue; | ||
| total += OutputGetCredit(wallet, txout, ISMINE_SPENDABLE); | ||
|
Comment on lines
+346
to
+348
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In a private-key-disabled watch-only wallet without an external signer, Useful? React with 👍 / 👎.
Comment on lines
+346
to
+348
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Blocking: Subtract locked watch-only outputs too
source: ['codex']
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The underreport is real, but it is inherited 1:1 from the backported upstream |
||
| } | ||
| return total; | ||
| } | ||
|
|
||
| std::map<CTxDestination, CAmount> GetAddressBalances(const CWallet& wallet) | ||
| { | ||
| std::map<CTxDestination, CAmount> balances; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.