Skip to content

Commit e800d9d

Browse files
committed
fix: hold wallet shared pointer in CJ Manager/Sessions to prevent concurrent unload
1 parent a82d33e commit e800d9d

File tree

8 files changed

+96
-107
lines changed

8 files changed

+96
-107
lines changed

src/coinjoin/client.cpp

Lines changed: 58 additions & 74 deletions
Large diffs are not rendered by default.

src/coinjoin/client.h

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class CoinJoinWalletManager {
9696
}
9797
}
9898

99-
void Add(CWallet& wallet);
99+
void Add(const std::shared_ptr<CWallet>& wallet);
100100
void DoMaintenance();
101101

102102
void Remove(const std::string& name);
@@ -138,7 +138,7 @@ class CoinJoinWalletManager {
138138
class CCoinJoinClientSession : public CCoinJoinBaseSession
139139
{
140140
private:
141-
CWallet& m_wallet;
141+
const std::shared_ptr<CWallet> m_wallet;
142142
CoinJoinWalletManager& m_walletman;
143143
CCoinJoinClientManager& m_clientman;
144144
CDeterministicMNManager& m_dmnman;
@@ -163,15 +163,15 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession
163163
/// Create denominations
164164
bool CreateDenominated(CAmount nBalanceToDenominate);
165165
bool CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals)
166-
EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet);
166+
EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet);
167167

168168
/// Split up large inputs or make fee sized inputs
169169
bool MakeCollateralAmounts();
170170
bool MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated)
171-
EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet);
171+
EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet);
172172

173173
bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason)
174-
EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet);
174+
EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet);
175175

176176
bool JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
177177
bool StartNewQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
@@ -181,7 +181,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession
181181
/// step 1: prepare denominated inputs and outputs
182182
bool PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, const std::vector<CTxDSIn>& vecTxDSIn,
183183
std::vector<std::pair<CTxDSIn, CTxOut>>& vecPSInOutPairsRet, bool fDryRun = false)
184-
EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet);
184+
EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet);
185185
/// step 2: send denominated inputs and outputs prepared in step 1
186186
bool SendDenominate(const std::vector<std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin);
187187

@@ -200,7 +200,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession
200200
void SetNull() override EXCLUSIVE_LOCKS_REQUIRED(cs_coinjoin);
201201

202202
public:
203-
explicit CCoinJoinClientSession(CWallet& wallet, CoinJoinWalletManager& walletman,
203+
explicit CCoinJoinClientSession(const std::shared_ptr<CWallet>& wallet, CoinJoinWalletManager& walletman,
204204
CCoinJoinClientManager& clientman, CDeterministicMNManager& dmnman,
205205
CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync,
206206
const std::unique_ptr<CCoinJoinClientQueueManager>& queueman, bool is_masternode);
@@ -267,7 +267,7 @@ class CCoinJoinClientQueueManager : public CCoinJoinBaseManager
267267
class CCoinJoinClientManager
268268
{
269269
private:
270-
CWallet& m_wallet;
270+
const std::shared_ptr<CWallet> m_wallet;
271271
CoinJoinWalletManager& m_walletman;
272272
CDeterministicMNManager& m_dmnman;
273273
CMasternodeMetaMan& m_mn_metaman;
@@ -306,11 +306,19 @@ class CCoinJoinClientManager
306306
CCoinJoinClientManager(CCoinJoinClientManager const&) = delete;
307307
CCoinJoinClientManager& operator=(CCoinJoinClientManager const&) = delete;
308308

309-
explicit CCoinJoinClientManager(CWallet& wallet, CoinJoinWalletManager& walletman, CDeterministicMNManager& dmnman,
310-
CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync,
309+
explicit CCoinJoinClientManager(const std::shared_ptr<CWallet>& wallet, CoinJoinWalletManager& walletman,
310+
CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman,
311+
const CMasternodeSync& mn_sync,
311312
const std::unique_ptr<CCoinJoinClientQueueManager>& queueman, bool is_masternode) :
312-
m_wallet(wallet), m_walletman(walletman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), m_queueman(queueman),
313-
m_is_masternode{is_masternode} {}
313+
m_wallet(wallet),
314+
m_walletman(walletman),
315+
m_dmnman(dmnman),
316+
m_mn_metaman(mn_metaman),
317+
m_mn_sync(mn_sync),
318+
m_queueman(queueman),
319+
m_is_masternode{is_masternode}
320+
{
321+
}
314322

315323
void ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
316324

src/coinjoin/interfaces.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,7 @@ class CoinJoinLoaderImpl : public interfaces::CoinJoin::Loader
6767
explicit CoinJoinLoaderImpl(CoinJoinWalletManager& walletman)
6868
: m_walletman(walletman) {}
6969

70-
void AddWallet(CWallet& wallet) override
71-
{
72-
m_walletman.Add(wallet);
73-
}
70+
void AddWallet(const std::shared_ptr<CWallet>& wallet) override { m_walletman.Add(wallet); }
7471
void RemoveWallet(const std::string& name) override
7572
{
7673
m_walletman.Remove(name);

src/coinjoin/util.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ bool CTransactionBuilderOutput::UpdateAmount(const CAmount nNewAmount)
108108
return true;
109109
}
110110

111-
CTransactionBuilder::CTransactionBuilder(std::shared_ptr<CWallet> pwalletIn, const CompactTallyItem& tallyItemIn) :
111+
CTransactionBuilder::CTransactionBuilder(const std::shared_ptr<CWallet> pwalletIn, const CompactTallyItem& tallyItemIn) :
112112
pwallet(pwalletIn),
113113
dummyReserveDestination(pwalletIn.get()),
114114
tallyItem(tallyItemIn)

src/coinjoin/util.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class CTransactionBuilderOutput
7777
class CTransactionBuilder
7878
{
7979
/// Wallet the transaction will be build for
80-
std::shared_ptr<CWallet> pwallet;
80+
const std::shared_ptr<CWallet> pwallet;
8181
/// See CTransactionBuilder() for initialization
8282
CCoinControl coinControl;
8383
/// Dummy since we anyway use tallyItem's destination as change destination in coincontrol.
@@ -100,7 +100,7 @@ class CTransactionBuilder
100100
friend class CTransactionBuilderOutput;
101101

102102
public:
103-
CTransactionBuilder(std::shared_ptr<CWallet> pwalletIn, const CompactTallyItem& tallyItemIn);
103+
CTransactionBuilder(const std::shared_ptr<CWallet> pwalletIn, const CompactTallyItem& tallyItemIn);
104104
~CTransactionBuilder();
105105
/// Check it would be possible to add a single output with the amount nAmount. Returns true if its possible and false if not.
106106
bool CouldAddOutput(CAmount nAmountOutput) const EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);

src/interfaces/coinjoin.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class Loader
3333
public:
3434
virtual ~Loader() {}
3535
//! Add new wallet to CoinJoin client manager
36-
virtual void AddWallet(CWallet&) = 0;
36+
virtual void AddWallet(const std::shared_ptr<CWallet>&) = 0;
3737
//! Remove wallet from CoinJoin client manager
3838
virtual void RemoveWallet(const std::string&) = 0;
3939
virtual void FlushWallet(const std::string&) = 0;

src/wallet/wallet.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ bool AddWallet(const std::shared_ptr<CWallet>& wallet)
125125
}
126126
wallet->ConnectScriptPubKeyManNotifiers();
127127
wallet->AutoLockMasternodeCollaterals();
128-
wallet->coinjoin_loader().AddWallet(*wallet);
128+
wallet->coinjoin_loader().AddWallet(wallet);
129129
wallet->NotifyCanGetAddressesChanged();
130130
return true;
131131
}
@@ -1432,46 +1432,46 @@ int CWallet::GetRealOutpointCoinJoinRounds(const COutPoint& outpoint, int nRound
14321432
if (wtx == nullptr || wtx->tx == nullptr) {
14331433
// no such tx in this wallet
14341434
*nRoundsRef = -1;
1435-
WalletCJLogPrint((*this), "%s FAILED %-70s %3d\n", __func__, outpoint.ToStringShort(), -1);
1435+
WalletCJLogPrint(this, "%s FAILED %-70s %3d\n", __func__, outpoint.ToStringShort(), -1);
14361436
return *nRoundsRef;
14371437
}
14381438

14391439
// bounds check
14401440
if (outpoint.n >= wtx->tx->vout.size()) {
14411441
// should never actually hit this
14421442
*nRoundsRef = -4;
1443-
WalletCJLogPrint((*this), "%s FAILED %-70s %3d\n", __func__, outpoint.ToStringShort(), -4);
1443+
WalletCJLogPrint(this, "%s FAILED %-70s %3d\n", __func__, outpoint.ToStringShort(), -4);
14441444
return *nRoundsRef;
14451445
}
14461446

14471447
auto txOutRef = &wtx->tx->vout[outpoint.n];
14481448

14491449
if (CoinJoin::IsCollateralAmount(txOutRef->nValue)) {
14501450
*nRoundsRef = -3;
1451-
WalletCJLogPrint((*this), "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
1451+
WalletCJLogPrint(this, "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
14521452
return *nRoundsRef;
14531453
}
14541454

14551455
// make sure the final output is non-denominate
14561456
if (!CoinJoin::IsDenominatedAmount(txOutRef->nValue)) { //NOT DENOM
14571457
*nRoundsRef = -2;
1458-
WalletCJLogPrint((*this), "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
1458+
WalletCJLogPrint(this, "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
14591459
return *nRoundsRef;
14601460
}
14611461

14621462
for (const auto& out : wtx->tx->vout) {
14631463
if (!CoinJoin::IsDenominatedAmount(out.nValue)) {
14641464
// this one is denominated but there is another non-denominated output found in the same tx
14651465
*nRoundsRef = 0;
1466-
WalletCJLogPrint((*this), "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
1466+
WalletCJLogPrint(this, "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
14671467
return *nRoundsRef;
14681468
}
14691469
}
14701470

14711471
// make sure we spent all of it with 0 fee, reset to 0 rounds otherwise
14721472
if (wtx->GetDebit(ISMINE_SPENDABLE) != wtx->GetCredit(ISMINE_SPENDABLE)) {
14731473
*nRoundsRef = 0;
1474-
WalletCJLogPrint((*this), "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
1474+
WalletCJLogPrint(this, "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
14751475
return *nRoundsRef;
14761476
}
14771477

@@ -1491,7 +1491,7 @@ int CWallet::GetRealOutpointCoinJoinRounds(const COutPoint& outpoint, int nRound
14911491
*nRoundsRef = fDenomFound
14921492
? (nShortest >= nRoundsMax - 1 ? nRoundsMax : nShortest + 1) // good, we a +1 to the shortest one but only nRoundsMax rounds max allowed
14931493
: 0; // too bad, we are the fist one in that chain
1494-
WalletCJLogPrint((*this), "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
1494+
WalletCJLogPrint(this, "%s UPDATED %-70s %3d\n", __func__, outpoint.ToStringShort(), *nRoundsRef);
14951495
return *nRoundsRef;
14961496
}
14971497

@@ -3253,7 +3253,7 @@ bool CWallet::SelectTxDSInsByDenomination(int nDenom, CAmount nValueMax, std::ve
32533253
CCoinControl coin_control;
32543254
coin_control.nCoinType = CoinType::ONLY_READY_TO_MIX;
32553255
AvailableCoins(vCoins, &coin_control);
3256-
WalletCJLogPrint((*this), "CWallet::%s -- vCoins.size(): %d\n", __func__, vCoins.size());
3256+
WalletCJLogPrint(this, "CWallet::%s -- vCoins.size(): %d\n", __func__, vCoins.size());
32573257

32583258
Shuffle(vCoins.rbegin(), vCoins.rend(), FastRandomContext());
32593259

@@ -3271,11 +3271,11 @@ bool CWallet::SelectTxDSInsByDenomination(int nDenom, CAmount nValueMax, std::ve
32713271
nValueTotal += nValue;
32723272
vecTxDSInRet.emplace_back(CTxDSIn(txin, scriptPubKey, nRounds));
32733273
setRecentTxIds.emplace(txHash);
3274-
WalletCJLogPrint((*this), "CWallet::%s -- hash: %s, nValue: %d.%08d\n",
3274+
WalletCJLogPrint(this, "CWallet::%s -- hash: %s, nValue: %d.%08d\n",
32753275
__func__, txHash.ToString(), nValue / COIN, nValue % COIN);
32763276
}
32773277

3278-
WalletCJLogPrint((*this), "CWallet::%s -- setRecentTxIds.size(): %d\n", __func__, setRecentTxIds.size());
3278+
WalletCJLogPrint(this, "CWallet::%s -- setRecentTxIds.size(): %d\n", __func__, setRecentTxIds.size());
32793279

32803280
return nValueTotal > 0;
32813281
}
@@ -4980,7 +4980,7 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain* chain, interfaces::C
49804980
}
49814981

49824982
if (coinjoin_loader) {
4983-
coinjoin_loader->AddWallet(*walletInstance);
4983+
coinjoin_loader->AddWallet(walletInstance);
49844984
}
49854985

49864986
{

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ extern const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS;
153153
#define WalletCJLogPrint(wallet, ...) \
154154
do { \
155155
if (LogAcceptCategory(BCLog::COINJOIN, BCLog::Level::Debug)) { \
156-
wallet.WalletLogPrintf(__VA_ARGS__); \
156+
wallet->WalletLogPrintf(__VA_ARGS__); \
157157
} \
158158
} while (0)
159159

0 commit comments

Comments
 (0)