Skip to content

Commit 460c187

Browse files
committed
refactor: move some CoinJoin-specific logic out of CWalletTx and CWallet
1 parent ed12dab commit 460c187

File tree

6 files changed

+63
-60
lines changed

6 files changed

+63
-60
lines changed

src/wallet/coinjoin.cpp

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -410,14 +410,14 @@ void CWallet::RecalculateMixedCredit(const uint256 hash)
410410
fAnonymizableTallyCachedNonDenom = false;
411411
}
412412

413-
CAmount CWallet::GetBalanceAnonymized(const CCoinControl& coinControl) const
413+
CAmount GetBalanceAnonymized(const CWallet& wallet, const CCoinControl& coinControl)
414414
{
415415
if (!CCoinJoinClientOptions::IsEnabled()) return 0;
416416

417417
CAmount anonymized_amount{0};
418-
LOCK(cs_wallet);
419-
for (auto pcoin : GetSpendableTXs()) {
420-
anonymized_amount += pcoin->GetAnonymizedCredit(coinControl);
418+
LOCK(wallet.cs_wallet);
419+
for (auto pcoin : wallet.GetSpendableTXs()) {
420+
anonymized_amount += CachedTxGetAnonymizedCredit(wallet, *pcoin, coinControl);
421421
}
422422
return anonymized_amount;
423423
}
@@ -490,32 +490,29 @@ CAmount CWallet::GetNormalizedAnonymizedBalance() const
490490
return nTotal;
491491
}
492492

493-
CAmount CWalletTx::GetAnonymizedCredit(const CCoinControl& coinControl) const
493+
CAmount CachedTxGetAnonymizedCredit(const CWallet& wallet, const CWalletTx& wtx, const CCoinControl& coinControl)
494494
{
495-
if (!pwallet)
496-
return 0;
497-
498-
AssertLockHeld(pwallet->cs_wallet);
495+
AssertLockHeld(wallet.cs_wallet);
499496

500497
// Exclude coinbase and conflicted txes
501-
if (IsCoinBase() || GetDepthInMainChain() < 0)
498+
if (wtx.IsCoinBase() || wtx.GetDepthInMainChain() < 0)
502499
return 0;
503500

504501
CAmount nCredit = 0;
505-
uint256 hashTx = GetHash();
506-
for (unsigned int i = 0; i < tx->vout.size(); i++)
502+
uint256 hashTx = wtx.GetHash();
503+
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++)
507504
{
508-
const CTxOut &txout = tx->vout[i];
505+
const CTxOut &txout = wtx.tx->vout[i];
509506
const COutPoint outpoint = COutPoint(hashTx, i);
510507

511508
if (coinControl.HasSelected() && !coinControl.IsSelected(outpoint)) {
512509
continue;
513510
}
514511

515-
if (pwallet->IsSpent(hashTx, i) || !CoinJoin::IsDenominatedAmount(txout.nValue)) continue;
512+
if (wallet.IsSpent(hashTx, i) || !CoinJoin::IsDenominatedAmount(txout.nValue)) continue;
516513

517-
if (pwallet->IsFullyMixed(outpoint)) {
518-
nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
514+
if (wallet.IsFullyMixed(outpoint)) {
515+
nCredit += wallet.GetCredit(txout, ISMINE_SPENDABLE);
519516
if (!MoneyRange(nCredit))
520517
throw std::runtime_error(std::string(__func__) + ": value out of range");
521518
}
@@ -524,40 +521,38 @@ CAmount CWalletTx::GetAnonymizedCredit(const CCoinControl& coinControl) const
524521
return nCredit;
525522
}
526523

527-
CWalletTx::CoinJoinCredits CWalletTx::GetAvailableCoinJoinCredits() const
524+
CoinJoinCredits CachedTxGetAvailableCoinJoinCredits(const CWallet& wallet, const CWalletTx& wtx)
528525
{
529-
CWalletTx::CoinJoinCredits ret;
530-
if (pwallet == nullptr)
531-
return ret;
526+
CoinJoinCredits ret;
532527

533-
AssertLockHeld(pwallet->cs_wallet);
528+
AssertLockHeld(wallet.cs_wallet);
534529

535530
// Must wait until coinbase is safely deep enough in the chain before valuing it
536-
if (IsCoinBase() && GetBlocksToMaturity() > 0)
531+
if (wtx.IsCoinBase() && wtx.GetBlocksToMaturity() > 0)
537532
return ret;
538533

539-
int nDepth = GetDepthInMainChain();
534+
int nDepth = wtx.GetDepthInMainChain();
540535
if (nDepth < 0) return ret;
541536

542-
ret.is_unconfirmed = IsTrusted() && nDepth == 0;
537+
ret.is_unconfirmed = wtx.IsTrusted() && nDepth == 0;
543538

544-
if (m_amounts[ANON_CREDIT].m_cached[ISMINE_SPENDABLE]) {
545-
if (ret.is_unconfirmed && m_amounts[DENOM_UCREDIT].m_cached[ISMINE_SPENDABLE]) {
546-
return {m_amounts[ANON_CREDIT].m_value[ISMINE_SPENDABLE], m_amounts[DENOM_UCREDIT].m_value[ISMINE_SPENDABLE], ret.is_unconfirmed};
547-
} else if (!ret.is_unconfirmed && m_amounts[DENOM_CREDIT].m_cached[ISMINE_SPENDABLE]) {
548-
return {m_amounts[ANON_CREDIT].m_value[ISMINE_SPENDABLE], m_amounts[DENOM_CREDIT].m_value[ISMINE_SPENDABLE], ret.is_unconfirmed};
539+
if (wtx.m_amounts[CWalletTx::ANON_CREDIT].m_cached[ISMINE_SPENDABLE]) {
540+
if (ret.is_unconfirmed && wtx.m_amounts[CWalletTx::DENOM_UCREDIT].m_cached[ISMINE_SPENDABLE]) {
541+
return {wtx.m_amounts[CWalletTx::ANON_CREDIT].m_value[ISMINE_SPENDABLE], wtx.m_amounts[CWalletTx::DENOM_UCREDIT].m_value[ISMINE_SPENDABLE], ret.is_unconfirmed};
542+
} else if (!ret.is_unconfirmed && wtx.m_amounts[CWalletTx::DENOM_CREDIT].m_cached[ISMINE_SPENDABLE]) {
543+
return {wtx.m_amounts[CWalletTx::ANON_CREDIT].m_value[ISMINE_SPENDABLE], wtx.m_amounts[CWalletTx::DENOM_CREDIT].m_value[ISMINE_SPENDABLE], ret.is_unconfirmed};
549544
}
550545
}
551546

552-
uint256 hashTx = GetHash();
553-
for (unsigned int i = 0; i < tx->vout.size(); i++) {
554-
const CTxOut &txout = tx->vout[i];
547+
uint256 hashTx = wtx.GetHash();
548+
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
549+
const CTxOut &txout = wtx.tx->vout[i];
555550
const COutPoint outpoint = COutPoint(hashTx, i);
556551

557-
if (pwallet->IsSpent(hashTx, i) || !CoinJoin::IsDenominatedAmount(txout.nValue)) continue;
558-
const CAmount credit = pwallet->GetCredit(txout, ISMINE_SPENDABLE);
552+
if (wallet.IsSpent(hashTx, i) || !CoinJoin::IsDenominatedAmount(txout.nValue)) continue;
553+
const CAmount credit = wallet.GetCredit(txout, ISMINE_SPENDABLE);
559554

560-
if (pwallet->IsFullyMixed(outpoint)) {
555+
if (wallet.IsFullyMixed(outpoint)) {
561556
ret.m_anonymized += credit;
562557
if (!MoneyRange(ret.m_anonymized))
563558
throw std::runtime_error(std::string(__func__) + ": value out of range");
@@ -568,11 +563,11 @@ CWalletTx::CoinJoinCredits CWalletTx::GetAvailableCoinJoinCredits() const
568563
throw std::runtime_error(std::string(__func__) + ": value out of range");
569564
}
570565

571-
m_amounts[ANON_CREDIT].Set(ISMINE_SPENDABLE, ret.m_anonymized);
566+
wtx.m_amounts[CWalletTx::ANON_CREDIT].Set(ISMINE_SPENDABLE, ret.m_anonymized);
572567
if (ret.is_unconfirmed) {
573-
m_amounts[DENOM_UCREDIT].Set(ISMINE_SPENDABLE, ret.m_denominated);
568+
wtx.m_amounts[CWalletTx::DENOM_UCREDIT].Set(ISMINE_SPENDABLE, ret.m_denominated);
574569
} else {
575-
m_amounts[DENOM_CREDIT].Set(ISMINE_SPENDABLE, ret.m_denominated);
570+
wtx.m_amounts[CWalletTx::DENOM_CREDIT].Set(ISMINE_SPENDABLE, ret.m_denominated);
576571
}
577572
return ret;
578573
}

src/wallet/coinjoin.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
#ifndef BITCOIN_WALLET_COINJOIN_H
77
#define BITCOIN_WALLET_COINJOIN_H
88

9+
#include <consensus/amount.h>
10+
#include <threadsafety.h>
11+
#include <wallet/wallet.h>
12+
13+
class CCoinControl;
14+
class CWallet;
15+
class CWalletTx;
16+
917
// Use a macro instead of a function for conditional logging to prevent
1018
// evaluating arguments when logging for the category is not enabled.
1119
#define WalletCJLogPrint(wallet, ...) \
@@ -15,4 +23,19 @@
1523
} \
1624
} while (0)
1725

26+
CAmount GetBalanceAnonymized(const CWallet& wallet, const CCoinControl& coinControl);
27+
28+
CAmount CachedTxGetAnonymizedCredit(const CWallet& wallet, const CWalletTx& wtx, const CCoinControl& coinControl)
29+
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
30+
31+
struct CoinJoinCredits
32+
{
33+
CAmount m_anonymized{0};
34+
CAmount m_denominated{0};
35+
bool is_unconfirmed{false};
36+
};
37+
38+
CoinJoinCredits CachedTxGetAvailableCoinJoinCredits(const CWallet& wallet, const CWalletTx& wtx)
39+
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
40+
1841
#endif // BITCOIN_WALLET_COINJOIN_H

src/wallet/interfaces.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <util/translation.h>
2222
#include <util/ui_change_type.h>
2323
#include <validation.h>
24+
#include <wallet/coinjoin.h>
2425
#include <wallet/context.h>
2526
#include <wallet/fees.h>
2627
#include <wallet/ismine.h>
@@ -424,7 +425,7 @@ class WalletImpl : public Wallet
424425
CAmount getAvailableBalance(const CCoinControl& coin_control) override
425426
{
426427
if (coin_control.IsUsingCoinJoin()) {
427-
return m_wallet->GetBalanceAnonymized(coin_control);
428+
return GetBalanceAnonymized(*m_wallet, coin_control);
428429
} else {
429430
return m_wallet->GetAvailableBalance(&coin_control);
430431
}

src/wallet/receive.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <coinjoin/options.h>
66
#include <consensus/consensus.h>
7+
#include <wallet/coinjoin.h>
78
#include <wallet/receive.h>
89
#include <wallet/transaction.h>
910
#include <wallet/wallet.h>
@@ -339,7 +340,7 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, const bool avoid_reuse
339340
ret.m_mine_immature += wtx.GetImmatureCredit();
340341
ret.m_watchonly_immature += wtx.GetImmatureWatchOnlyCredit();
341342
if (cj_enabled) {
342-
const auto balance_anonymized = wtx.GetAvailableCoinJoinCredits();
343+
const auto balance_anonymized = CachedTxGetAvailableCoinJoinCredits(*this, wtx);
343344
ret.m_anonymized += balance_anonymized.m_anonymized;
344345
if (balance_anonymized.is_unconfirmed) {
345346
ret.m_denominated_untrusted_pending += balance_anonymized.m_denominated;

src/wallet/transaction.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -285,22 +285,6 @@ class CWalletTx
285285
CAmount GetImmatureWatchOnlyCredit(const bool fUseCache = true) const;
286286
CAmount GetChange() const;
287287

288-
struct CoinJoinCredits
289-
{
290-
CAmount m_anonymized{0};
291-
CAmount m_denominated{0};
292-
bool is_unconfirmed{false};
293-
};
294-
295-
// TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
296-
// annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The
297-
// annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid
298-
// having to resolve the issue of member access into incomplete type CWallet.
299-
/* Requires cs_wallet lock. */
300-
CAmount GetAnonymizedCredit(const CCoinControl& coinControl) const NO_THREAD_SAFETY_ANALYSIS;
301-
/* Requires cs_wallet lock. */
302-
CoinJoinCredits GetAvailableCoinJoinCredits() const NO_THREAD_SAFETY_ANALYSIS;
303-
304288
/** Get the marginal bytes if spending the specified output from this transaction */
305289
int GetSpendSize(unsigned int out, bool use_max_sig = false) const
306290
{

src/wallet/wallet.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,6 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
356356
/** Internal database handle. */
357357
std::unique_ptr<WalletDatabase> const m_database;
358358

359-
// A helper function which loops through wallet UTXOs
360-
std::unordered_set<const CWalletTx*, WalletTxHasher> GetSpendableTXs() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
361-
362359
/**
363360
* The following is used to keep track of how far behind the wallet is
364361
* from the chain sync, and to allow clients to block on us being caught up.
@@ -474,6 +471,9 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
474471

475472
void UpdateProgress(const std::string& title, int nProgress) override;
476473

474+
/* A helper function which loops through wallet UTXOs */
475+
std::unordered_set<const CWalletTx*, WalletTxHasher> GetSpendableTXs() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
476+
477477
/** Map from txid to CWalletTx for all transactions this wallet is
478478
* interested in, including received and sent transactions. */
479479
std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
@@ -666,7 +666,6 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
666666
CAmount m_denominated_untrusted_pending{0};
667667
};
668668
Balance GetBalance(const int min_depth = 0, const bool avoid_reuse = true, const bool fAddLocked = false) const;
669-
CAmount GetBalanceAnonymized(const CCoinControl& coinControl) const;
670669

671670
CAmount GetAnonymizableBalance(bool fSkipDenominated = false, bool fSkipUnconfirmed = true) const;
672671
float GetAverageAnonymizedRounds() const;

0 commit comments

Comments
 (0)