From 41a6613fba2e7285d9e30f306c17bb74468d5b5d Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Wed, 13 Sep 2023 23:22:38 +0530 Subject: [PATCH] refactor: subsume CoinJoin objects under CJContext, deglobalize coinJoin{ClientQueueManager,Server} (#5337) ## Motivation CoinJoin's subsystems are initialized by variables and managers that occupy the global context. The _extent_ to which these subsystems entrench themselves into the codebase is difficult to assess and moving them out of the global context forces us to enumerate the subsystems in the codebase that rely on CoinJoin logic and enumerate the order in which components are initialized and destroyed. Keeping this in mind, the scope of this pull request aims to: * Reduce the amount of CoinJoin-specific entities present in the global scope * Make the remaining usage of these entities in the global scope explicit and easily searchable ## Additional Information * The initialization of `CCoinJoinClientQueueManager` is dependent on blocks-only mode being disabled (which can be alternatively interpreted as enabling the relay of transactions). The same applies to `CBlockPolicyEstimator`, which `CCoinJoinClientQueueManager` depends. Therefore, `CCoinJoinClientQueueManager` is only initialized if transaction relaying is enabled and so is its scheduled maintenance task. This can be found by looking at `init.cpp` [here](https://github.com/dashpay/dash/blob/93f8df1c31fdce6a14f149acfdff22678c3f22ca/src/init.cpp#L1681-L1683), [here](https://github.com/dashpay/dash/blob/93f8df1c31fdce6a14f149acfdff22678c3f22ca/src/init.cpp#L2253-L2255) and [here](https://github.com/dashpay/dash/blob/93f8df1c31fdce6a14f149acfdff22678c3f22ca/src/init.cpp#L2326-L2327). For this reason, `CBlockPolicyEstimator` is not a member of `CJContext` and its usage is fulfilled by passing it as a reference when initializing the scheduling task. * `CJClientManager` has not used `CConnman` or `CTxMemPool` as `const` as existing code that is outside the scope of this PR would cast away constness, which would be unacceptable. Furthermore, some logical paths are taken that will grind to a halt if they are stored as `const`. Examples of such a call chains would be: * `CJClientManager::DoMaintenance > CCoinJoinClientManager::DoMaintenance > DoAutomaticDenominating > CCoinJoinClientSession::DoAutomaticDenominating > CCoinJoinClientSession::StartNewQueue > CConnman::AddPendingMasternode` which modifies `CConnman::vPendingMasternodes`, which is non-const behaviour * `CJClientManager::DoMaintenance > CCoinJoinClientManager::DoMaintenance > DoAutomaticDenominating > CCoinJoin::IsCollateralValid > AcceptToMemoryPool` which adds a transaction to the memory pool, which is non-const behaviour * There were cppcheck [linter failures](https://github.com/dashpay/dash/pull/5337#issuecomment-1685084688) that seemed to be caused by the usage of `Assert` in `coinjoin/client.h`. This seems to be resolved by backporting [bitcoin#24714](https://github.com/bitcoin/bitcoin/pull/24714). (Thanks @knst!) * Depends on #5546 --------- Co-authored-by: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> --- src/Makefile.am | 2 + src/coinjoin/client.cpp | 343 ++++++++++++------------ src/coinjoin/client.h | 93 +++++-- src/coinjoin/context.cpp | 34 +++ src/coinjoin/context.h | 39 +++ src/coinjoin/server.cpp | 11 +- src/coinjoin/server.h | 5 +- src/dsnotificationinterface.cpp | 8 +- src/dsnotificationinterface.h | 5 +- src/dummywallet.cpp | 4 +- src/init.cpp | 43 +-- src/interfaces/wallet.h | 7 +- src/masternode/utils.cpp | 6 +- src/masternode/utils.h | 3 +- src/net_processing.cpp | 20 +- src/net_processing.h | 5 +- src/node/context.cpp | 1 + src/node/context.h | 9 +- src/qt/test/addressbooktests.cpp | 4 +- src/qt/test/wallettests.cpp | 3 +- src/qt/walletcontroller.cpp | 6 +- src/rpc/coinjoin.cpp | 36 +-- src/test/denialofservice_tests.cpp | 15 +- src/test/util/setup_common.cpp | 15 +- src/wallet/init.cpp | 10 +- src/wallet/interfaces.cpp | 40 +-- src/wallet/load.cpp | 7 +- src/wallet/test/coinjoin_tests.cpp | 4 +- src/wallet/wallet.cpp | 26 +- src/walletinitinterface.h | 3 +- test/lint/lint-circular-dependencies.sh | 2 + 31 files changed, 477 insertions(+), 332 deletions(-) create mode 100644 src/coinjoin/context.cpp create mode 100644 src/coinjoin/context.h diff --git a/src/Makefile.am b/src/Makefile.am index 559382876e..9145ad2380 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -149,6 +149,7 @@ BITCOIN_CORE_H = \ clientversion.h \ coinjoin/coinjoin.h \ coinjoin/client.h \ + coinjoin/context.h \ coinjoin/options.h \ coinjoin/server.h \ coinjoin/util.h \ @@ -391,6 +392,7 @@ libbitcoin_server_a_SOURCES = \ blockfilter.cpp \ chain.cpp \ coinjoin/coinjoin.cpp \ + coinjoin/context.cpp \ coinjoin/options.cpp \ coinjoin/server.cpp \ consensus/tx_verify.cpp \ diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index 68176f76d9..5fd6f69172 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -3,9 +3,9 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include -#include #include +#include #include #include #include @@ -27,9 +27,7 @@ #include #include -std::map> coinJoinClientManagers; -std::unique_ptr coinJoinClientQueueManager; - +std::unique_ptr coinJoinClientManagers; void CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv) { @@ -99,7 +97,7 @@ void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, PeerManager& } // if the queue is ready, submit if we can - if (dsq.fReady && ranges::any_of(coinJoinClientManagers, + if (dsq.fReady && ranges::any_of(m_clientman.raw(), [this, &dmn](const auto &pair) { return pair.second->TrySubmitDenominate(dmn->pdmnState->addr, this->connman); @@ -124,7 +122,7 @@ void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, PeerManager& LogPrint(BCLog::COINJOIN, "DSQUEUE -- new CoinJoin queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString()); - ranges::any_of(coinJoinClientManagers, + ranges::any_of(m_clientman.raw(), [&dsq](const auto &pair) { return pair.second->MarkAlreadyJoinedQueueAsTried(dsq); }); WITH_LOCK(cs_vecqueue, vecCoinJoinQueue.push_back(dsq)); @@ -142,7 +140,7 @@ void CCoinJoinClientManager::ProcessMessage(CNode& peer, PeerManager& peerman, C if (!CheckDiskSpace(GetDataDir())) { ResetPool(); StopMixing(); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::ProcessMessage -- Not enough disk space, disabling CoinJoin.\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::ProcessMessage -- Not enough disk space, disabling CoinJoin.\n"); return; } @@ -185,11 +183,11 @@ void CCoinJoinClientSession::ProcessMessage(CNode& peer, PeerManager& peerman, C CTransaction txNew(deserialize, vRecv); if (nSessionID != nMsgSessionID) { - WalletCJLogPrint(mixingWallet, "DSFINALTX -- message doesn't match current CoinJoin session: nSessionID: %d nMsgSessionID: %d\n", nSessionID.load(), nMsgSessionID); + WalletCJLogPrint(m_wallet, "DSFINALTX -- message doesn't match current CoinJoin session: nSessionID: %d nMsgSessionID: %d\n", nSessionID.load(), nMsgSessionID); return; } - WalletCJLogPrint(mixingWallet, "DSFINALTX -- txNew %s", txNew.ToString()); /* Continued */ + WalletCJLogPrint(m_wallet, "DSFINALTX -- txNew %s", txNew.ToString()); /* Continued */ // check to see if input is spent already? (and probably not confirmed) SignFinalTransaction(mempool, txNew, peer, connman); @@ -197,7 +195,7 @@ void CCoinJoinClientSession::ProcessMessage(CNode& peer, PeerManager& peerman, C } else if (msg_type == NetMsgType::DSCOMPLETE) { if (!mixingMasternode) return; if (mixingMasternode->pdmnState->addr != peer.addr) { - WalletCJLogPrint(mixingWallet, "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", mixingMasternode->pdmnState->addr.ToString(), peer.addr.ToString()); + WalletCJLogPrint(m_wallet, "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", mixingMasternode->pdmnState->addr.ToString(), peer.addr.ToString()); return; } @@ -206,16 +204,16 @@ void CCoinJoinClientSession::ProcessMessage(CNode& peer, PeerManager& peerman, C vRecv >> nMsgSessionID >> nMsgMessageID; if (nMsgMessageID < MSG_POOL_MIN || nMsgMessageID > MSG_POOL_MAX) { - WalletCJLogPrint(mixingWallet, "DSCOMPLETE -- nMsgMessageID is out of bounds: %d\n", nMsgMessageID); + WalletCJLogPrint(m_wallet, "DSCOMPLETE -- nMsgMessageID is out of bounds: %d\n", nMsgMessageID); return; } if (nSessionID != nMsgSessionID) { - WalletCJLogPrint(mixingWallet, "DSCOMPLETE -- message doesn't match current CoinJoin session: nSessionID: %d nMsgSessionID: %d\n", nSessionID.load(), nMsgSessionID); + WalletCJLogPrint(m_wallet, "DSCOMPLETE -- message doesn't match current CoinJoin session: nSessionID: %d nMsgSessionID: %d\n", nSessionID.load(), nMsgSessionID); return; } - WalletCJLogPrint(mixingWallet, "DSCOMPLETE -- nMsgSessionID %d nMsgMessageID %d (%s)\n", nMsgSessionID, nMsgMessageID, CCoinJoin::GetMessageByID(nMsgMessageID).translated); + WalletCJLogPrint(m_wallet, "DSCOMPLETE -- nMsgSessionID %d nMsgMessageID %d (%s)\n", nMsgSessionID, nMsgMessageID, CCoinJoin::GetMessageByID(nMsgMessageID).translated); CompletedTransaction(nMsgMessageID); } @@ -273,13 +271,13 @@ void CCoinJoinClientSession::UnlockCoins() if (!CCoinJoinClientOptions::IsEnabled()) return; while (true) { - TRY_LOCK(mixingWallet.cs_wallet, lockWallet); + TRY_LOCK(m_wallet.cs_wallet, lockWallet); if (!lockWallet) { UninterruptibleSleep(std::chrono::milliseconds{50}); continue; } for (const auto& outpoint : vecOutPointLocked) - mixingWallet.UnlockCoin(outpoint); + m_wallet.UnlockCoin(outpoint); break; } @@ -383,7 +381,7 @@ bool CCoinJoinClientSession::CheckTimeout() if (nState == POOL_STATE_ERROR) { if (GetTime() - nTimeLastSuccessfulStep >= 10) { // reset after being in POOL_STATE_ERROR for 10 or more seconds - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- resetting session %d\n", __func__, nSessionID.load()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- resetting session %d\n", __func__, nSessionID.load()); WITH_LOCK(cs_coinjoin, SetNull()); } return false; @@ -395,7 +393,7 @@ bool CCoinJoinClientSession::CheckTimeout() if (!fTimeout) return false; - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- %s %d timed out (%ds)\n", __func__, + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- %s %d timed out (%ds)\n", __func__, (nState == POOL_STATE_SIGNING) ? "Signing at session" : "Session", nSessionID.load(), nTimeout); SetState(POOL_STATE_ERROR); @@ -432,18 +430,18 @@ void CCoinJoinClientManager::CheckTimeout() bool CCoinJoinClientSession::SendDenominate(const std::vector >& vecPSInOutPairsIn, CConnman& connman) { if (fMasternodeMode) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::SendDenominate -- CoinJoin from a Masternode is not supported currently.\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SendDenominate -- CoinJoin from a Masternode is not supported currently.\n"); return false; } if (CTransaction(txMyCollateral).IsNull()) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClient:SendDenominate -- CoinJoin collateral not set\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClient:SendDenominate -- CoinJoin collateral not set\n"); return false; } // we should already be connected to a Masternode if (!nSessionID) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::SendDenominate -- No Masternode has been selected yet.\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SendDenominate -- No Masternode has been selected yet.\n"); UnlockCoins(); keyHolderStorage.ReturnAll(); WITH_LOCK(cs_coinjoin, SetNull()); @@ -454,14 +452,14 @@ bool CCoinJoinClientSession::SendDenominate(const std::vector vecTxDSInTmp; @@ -474,7 +472,7 @@ bool CCoinJoinClientSession::SendDenominate(const std::vector POOL_STATE_MAX) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- psssup.nState is out of bounds: %d\n", __func__, psssup.nState); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- psssup.nState is out of bounds: %d\n", __func__, psssup.nState); return; } if (psssup.nMessageID < MSG_POOL_MIN || psssup.nMessageID > MSG_POOL_MAX) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- psssup.nMessageID is out of bounds: %d\n", __func__, psssup.nMessageID); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- psssup.nMessageID is out of bounds: %d\n", __func__, psssup.nMessageID); return; } @@ -508,7 +506,7 @@ void CCoinJoinClientSession::ProcessPoolStateUpdate(CCoinJoinStatusUpdate psssup switch (psssup.nStatusUpdate) { case STATUS_REJECTED: { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- rejected by Masternode: %s\n", __func__, strMessageTmp.translated); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- rejected by Masternode: %s\n", __func__, strMessageTmp.translated); SetState(POOL_STATE_ERROR); UnlockCoins(); keyHolderStorage.ReturnAll(); @@ -523,11 +521,11 @@ void CCoinJoinClientSession::ProcessPoolStateUpdate(CCoinJoinStatusUpdate psssup nTimeLastSuccessfulStep = GetTime(); strMessageTmp = strMessageTmp + strprintf(Untranslated(" Set nSessionID to %d."), nSessionID); } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- accepted by Masternode: %s\n", __func__, strMessageTmp.translated); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- accepted by Masternode: %s\n", __func__, strMessageTmp.translated); break; } default: { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- psssup.nStatusUpdate is out of bounds: %d\n", __func__, psssup.nStatusUpdate); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- psssup.nStatusUpdate is out of bounds: %d\n", __func__, psssup.nStatusUpdate); break; } } @@ -545,11 +543,11 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con if (fMasternodeMode) return false; if (!mixingMasternode) return false; - LOCK(mixingWallet.cs_wallet); + LOCK(m_wallet.cs_wallet); LOCK(cs_coinjoin); finalMutableTransaction = CMutableTransaction{finalTransactionNew}; - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- finalMutableTransaction=%s", __func__, finalMutableTransaction.ToString()); /* Continued */ + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- finalMutableTransaction=%s", __func__, finalMutableTransaction.ToString()); /* Continued */ // STEP 1: check final transaction general rules @@ -558,7 +556,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con sort(finalMutableTransaction.vout.begin(), finalMutableTransaction.vout.end(), CompareOutputBIP69()); if (finalMutableTransaction.GetHash() != finalTransactionNew.GetHash()) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- ERROR! Masternode %s is not BIP69 compliant!\n", __func__, mixingMasternode->proTxHash.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- ERROR! Masternode %s is not BIP69 compliant!\n", __func__, mixingMasternode->proTxHash.ToString()); UnlockCoins(); keyHolderStorage.ReturnAll(); SetNull(); @@ -568,7 +566,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con // Make sure all inputs/outputs are valid PoolMessage nMessageID{MSG_NOERR}; if (!IsValidInOuts(mempool, finalMutableTransaction.vin, finalMutableTransaction.vout, nMessageID, nullptr)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CCoinJoin::GetMessageByID(nMessageID).translated); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CCoinJoin::GetMessageByID(nMessageID).translated); UnlockCoins(); keyHolderStorage.ReturnAll(); SetNull(); @@ -588,7 +586,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con if (!fFound) { // Something went wrong and we'll refuse to sign. It's possible we'll be charged collateral. But that's // better than signing if the transaction doesn't look like what we wanted. - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- an output is missing, refusing to sign! txout=%s\n", __func__, txout.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- an output is missing, refusing to sign! txout=%s\n", __func__, txout.ToString()); UnlockCoins(); keyHolderStorage.ReturnAll(); SetNull(); @@ -613,29 +611,29 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con if (nMyInputIndex == -1) { // Can't find one of my own inputs, refuse to sign. It's possible we'll be charged collateral. But that's // better than signing if the transaction doesn't look like what we wanted. - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- missing input! txdsin=%s\n", __func__, txdsin.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- missing input! txdsin=%s\n", __func__, txdsin.ToString()); UnlockCoins(); keyHolderStorage.ReturnAll(); SetNull(); return false; } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- found my input %i\n", __func__, nMyInputIndex); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- found my input %i\n", __func__, nMyInputIndex); // add a pair with an empty value coins[finalMutableTransaction.vin.at(nMyInputIndex).prevout]; } } // fill values for found outpoints - mixingWallet.chain().findCoins(coins); + m_wallet.chain().findCoins(coins); std::map signing_errors; - mixingWallet.SignTransaction(finalMutableTransaction, coins, SIGHASH_ALL | SIGHASH_ANYONECANPAY, signing_errors); + m_wallet.SignTransaction(finalMutableTransaction, coins, SIGHASH_ALL | SIGHASH_ANYONECANPAY, signing_errors); for (const auto& [input_index, error_string] : signing_errors) { // NOTE: this is a partial signing so it's expected for SignTransaction to return // "Input not found or already spent" errors for inputs that aren't ours if (error_string != "Input not found or already spent") { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- signing input %d failed: %s!\n", __func__, input_index, error_string); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- signing input %d failed: %s!\n", __func__, input_index, error_string); UnlockCoins(); keyHolderStorage.ReturnAll(); SetNull(); @@ -651,7 +649,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con } if (signed_inputs.empty()) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- can't sign anything!\n", __func__); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- can't sign anything!\n", __func__); UnlockCoins(); keyHolderStorage.ReturnAll(); SetNull(); @@ -659,7 +657,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con } // push all of our signatures to the Masternode - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- pushing signed inputs to the masternode, finalMutableTransaction=%s", __func__, finalMutableTransaction.ToString()); /* Continued */ + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- pushing signed inputs to the masternode, finalMutableTransaction=%s", __func__, finalMutableTransaction.ToString()); /* Continued */ CNetMsgMaker msgMaker(peer.GetSendVersion()); connman.PushMessage(&peer, msgMaker.Make(NetMsgType::DSSIGNFINALTX, signed_inputs)); SetState(POOL_STATE_SIGNING); @@ -674,12 +672,12 @@ void CCoinJoinClientSession::CompletedTransaction(PoolMessage nMessageID) if (fMasternodeMode) return; if (nMessageID == MSG_SUCCESS) { - WalletCJLogPrint(mixingWallet, "CompletedTransaction -- success\n"); - coinJoinClientManagers.at(mixingWallet.GetName())->UpdatedSuccessBlock(); + m_manager.UpdatedSuccessBlock(); keyHolderStorage.KeepAll(); + WalletCJLogPrint(m_wallet, "CompletedTransaction -- success\n"); } else { - WalletCJLogPrint(mixingWallet, "CompletedTransaction -- error\n"); keyHolderStorage.ReturnAll(); + WalletCJLogPrint(m_wallet, "CompletedTransaction -- error\n"); } UnlockCoins(); WITH_LOCK(cs_coinjoin, SetNull()); @@ -708,52 +706,52 @@ bool CCoinJoinClientManager::CheckAutomaticBackup() switch (nWalletBackups) { case 0: strAutoDenomResult = _("Automatic backups disabled") + Untranslated(", ") + _("no mixing available."); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); StopMixing(); - mixingWallet.nKeysLeftSinceAutoBackup = 0; // no backup, no "keys since last backup" + m_wallet.nKeysLeftSinceAutoBackup = 0; // no backup, no "keys since last backup" return false; case -1: // Automatic backup failed, nothing else we can do until user fixes the issue manually. // There is no way to bring user attention in daemon mode, so we just update status and // keep spamming if debug is on. strAutoDenomResult = _("ERROR! Failed to create automatic backup") + Untranslated(", ") + _("see debug.log for details."); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); return false; case -2: // We were able to create automatic backup but keypool was not replenished because wallet is locked. // There is no way to bring user attention in daemon mode, so we just update status and // keep spamming if debug is on. strAutoDenomResult = _("WARNING! Failed to replenish keypool, please unlock your wallet to do so.") + Untranslated(", ") + _("see debug.log for details."); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); return false; } - if (mixingWallet.nKeysLeftSinceAutoBackup < COINJOIN_KEYS_THRESHOLD_STOP) { + if (m_wallet.nKeysLeftSinceAutoBackup < COINJOIN_KEYS_THRESHOLD_STOP) { // We should never get here via mixing itself but probably something else is still actively using keypool - strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + Untranslated(", ") + _("no mixing available."), mixingWallet.nKeysLeftSinceAutoBackup); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); + strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + Untranslated(", ") + _("no mixing available."), m_wallet.nKeysLeftSinceAutoBackup); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); // It's getting really dangerous, stop mixing StopMixing(); return false; - } else if (mixingWallet.nKeysLeftSinceAutoBackup < COINJOIN_KEYS_THRESHOLD_WARNING) { + } else if (m_wallet.nKeysLeftSinceAutoBackup < COINJOIN_KEYS_THRESHOLD_WARNING) { // Low number of keys left, but it's still more or less safe to continue - strAutoDenomResult = strprintf(_("Very low number of keys left: %d"), mixingWallet.nKeysLeftSinceAutoBackup); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); + strAutoDenomResult = strprintf(_("Very low number of keys left: %d"), m_wallet.nKeysLeftSinceAutoBackup); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); if (fCreateAutoBackups) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::CheckAutomaticBackup -- Trying to create new backup.\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::CheckAutomaticBackup -- Trying to create new backup.\n"); bilingual_str errorString; std::vector warnings; - if (!mixingWallet.AutoBackupWallet("", errorString, warnings)) { + if (!m_wallet.AutoBackupWallet("", errorString, warnings)) { if (!warnings.empty()) { // There were some issues saving backup but yet more or less safe to continue - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::CheckAutomaticBackup -- WARNING! Something went wrong on automatic backup: %s\n", Join(warnings, Untranslated("\n")).translated); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::CheckAutomaticBackup -- WARNING! Something went wrong on automatic backup: %s\n", Join(warnings, Untranslated("\n")).translated); } if (!errorString.original.empty()) { // Things are really broken strAutoDenomResult = _("ERROR! Failed to create automatic backup") + Untranslated(": ") + errorString; - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original); return false; } } @@ -763,7 +761,7 @@ bool CCoinJoinClientManager::CheckAutomaticBackup() } } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::CheckAutomaticBackup -- Keys left since latest backup: %d\n", mixingWallet.nKeysLeftSinceAutoBackup); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::CheckAutomaticBackup -- Keys left since latest backup: %d\n", m_wallet.nKeysLeftSinceAutoBackup); return true; } @@ -786,9 +784,9 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CBlockPo CAmount nBalanceNeedsAnonymized; { - LOCK(mixingWallet.cs_wallet); + LOCK(m_wallet.cs_wallet); - if (!fDryRun && mixingWallet.IsLocked(true)) { + if (!fDryRun && m_wallet.IsLocked(true)) { strAutoDenomResult = _("Wallet is locked."); return false; } @@ -807,18 +805,18 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CBlockPo if (deterministicMNManager->GetListAtChainTip().GetValidMNsCount() == 0 && Params().NetworkIDString() != CBaseChainParams::REGTEST) { strAutoDenomResult = _("No Masternodes detected."); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original); return false; } - const auto bal = mixingWallet.GetBalance(); + const auto bal = m_wallet.GetBalance(); // check if there is anything left to do CAmount nBalanceAnonymized = bal.m_anonymized; nBalanceNeedsAnonymized = CCoinJoinClientOptions::GetAmount() * COIN - nBalanceAnonymized; if (nBalanceNeedsAnonymized < 0) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::DoAutomaticDenominating -- Nothing to do\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- Nothing to do\n"); // nothing to do, just keep it in idle mode return false; } @@ -826,23 +824,23 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CBlockPo CAmount nValueMin = CCoinJoin::GetSmallestDenomination(); // if there are no confirmed DS collateral inputs yet - if (!mixingWallet.HasCollateralInputs()) { + if (!m_wallet.HasCollateralInputs()) { // should have some additional amount for them nValueMin += CCoinJoin::GetMaxCollateralAmount(); } // including denoms but applying some restrictions - CAmount nBalanceAnonymizable = mixingWallet.GetAnonymizableBalance(); + CAmount nBalanceAnonymizable = m_wallet.GetAnonymizableBalance(); // mixable balance is way too small if (nBalanceAnonymizable < nValueMin) { strAutoDenomResult = _("Not enough funds to mix."); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original); return false; } // excluding denoms - CAmount nBalanceAnonimizableNonDenom = mixingWallet.GetAnonymizableBalance(true); + CAmount nBalanceAnonimizableNonDenom = m_wallet.GetAnonymizableBalance(true); // denoms CAmount nBalanceDenominatedConf = bal.m_denominated_trusted; CAmount nBalanceDenominatedUnconf = bal.m_denominated_untrusted_pending; @@ -863,7 +861,7 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CBlockPo nBalanceNeedsAnonymized += nAdditionalDenom; } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::DoAutomaticDenominating -- current stats:\n" + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- current stats:\n" " nValueMin: %s\n" " nBalanceAnonymizable: %s\n" " nBalanceAnonymized: %s\n" @@ -894,8 +892,8 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CBlockPo } //check if we have the collateral sized inputs - if (!mixingWallet.HasCollateralInputs()) { - return !mixingWallet.HasCollateralInputs(false) && MakeCollateralAmounts(fee_estimator); + if (!m_wallet.HasCollateralInputs()) { + return !m_wallet.HasCollateralInputs(false) && MakeCollateralAmounts(fee_estimator); } if (nSessionID) { @@ -912,7 +910,7 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CBlockPo // should be no unconfirmed denoms in non-multi-session mode if (!CCoinJoinClientOptions::IsMultiSessionEnabled() && nBalanceDenominatedUnconf > 0) { strAutoDenomResult = _("Found unconfirmed denominated outputs, will wait till they confirm to continue."); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original); return false; } @@ -920,24 +918,24 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CBlockPo std::string strReason; if (CTransaction(txMyCollateral).IsNull()) { if (!CreateCollateralTransaction(txMyCollateral, strReason)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::DoAutomaticDenominating -- create collateral error:%s\n", strReason); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- create collateral error:%s\n", strReason); return false; } } else { if (!CCoinJoin::IsCollateralValid(mempool, CTransaction(txMyCollateral))) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::DoAutomaticDenominating -- invalid collateral, recreating...\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- invalid collateral, recreating...\n"); if (!CreateCollateralTransaction(txMyCollateral, strReason)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::DoAutomaticDenominating -- create collateral error: %s\n", strReason); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- create collateral error: %s\n", strReason); return false; } } } // lock the funds we're going to use for our collateral for (const auto& txin : txMyCollateral.vin) { - mixingWallet.LockCoin(txin.prevout); + m_wallet.LockCoin(txin.prevout); vecOutPointLocked.push_back(txin.prevout); } - } // LOCK(mixingWallet.cs_wallet); + } // LOCK(m_wallet.cs_wallet); // Always attempt to join an existing queue if (JoinExistingQueue(nBalanceNeedsAnonymized, connman)) { @@ -961,7 +959,7 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(CConnman& connman, CBlockPo return false; } - if (!fDryRun && mixingWallet.IsLocked(true)) { + if (!fDryRun && m_wallet.IsLocked(true)) { strAutoDenomResult = _("Wallet is locked."); return false; } @@ -971,25 +969,25 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(CConnman& connman, CBlockPo // If we've used 90% of the Masternode list then drop the oldest first ~30% int nThreshold_high = nMnCountEnabled * 0.9; int nThreshold_low = nThreshold_high * 0.7; - WalletCJLogPrint(mixingWallet, "Checking vecMasternodesUsed: size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high); + WalletCJLogPrint(m_wallet, "Checking vecMasternodesUsed: size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high); if ((int)vecMasternodesUsed.size() > nThreshold_high) { vecMasternodesUsed.erase(vecMasternodesUsed.begin(), vecMasternodesUsed.begin() + vecMasternodesUsed.size() - nThreshold_low); - WalletCJLogPrint(mixingWallet, " vecMasternodesUsed: new size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high); + WalletCJLogPrint(m_wallet, " vecMasternodesUsed: new size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high); } bool fResult = true; AssertLockNotHeld(cs_deqsessions); LOCK(cs_deqsessions); if (int(deqSessions.size()) < CCoinJoinClientOptions::GetSessions()) { - deqSessions.emplace_back(mixingWallet, m_mn_sync); + deqSessions.emplace_back(m_wallet, m_clientman, m_mn_sync, m_queueman); } for (auto& session : deqSessions) { if (!CheckAutomaticBackup()) return false; if (WaitForAnotherBlock()) { strAutoDenomResult = _("Last successful action was too recent."); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original); return false; } @@ -1011,7 +1009,7 @@ CDeterministicMNCPtr CCoinJoinClientManager::GetRandomNotUsedMasternode() size_t nCountEnabled = mnList.GetValidMNsCount(); size_t nCountNotExcluded = nCountEnabled - vecMasternodesUsed.size(); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::%s -- %d enabled masternodes, %d masternodes to choose from\n", __func__, nCountEnabled, nCountNotExcluded); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::%s -- %d enabled masternodes, %d masternodes to choose from\n", __func__, nCountEnabled, nCountNotExcluded); if (nCountNotExcluded < 1) { return nullptr; } @@ -1034,11 +1032,11 @@ CDeterministicMNCPtr CCoinJoinClientManager::GetRandomNotUsedMasternode() continue; } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::%s -- found, masternode=%s\n", __func__, dmn->collateralOutpoint.ToStringShort()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::%s -- found, masternode=%s\n", __func__, dmn->collateralOutpoint.ToStringShort()); return dmn; } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::%s -- failed\n", __func__); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::%s -- failed\n", __func__); return nullptr; } @@ -1052,24 +1050,24 @@ static int WinnersToSkip() bool CCoinJoinClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman) { if (!CCoinJoinClientOptions::IsEnabled()) return false; - if (coinJoinClientQueueManager == nullptr) return false; + if (m_queueman == nullptr) return false; const auto mnList = deterministicMNManager->GetListAtChainTip(); const int nWeightedMnCount = mnList.GetValidWeightedMNsCount(); // Look through the queues and see if anything matches CCoinJoinQueue dsq; - while (coinJoinClientQueueManager->GetQueueItemAndTry(dsq)) { + while (m_queueman->GetQueueItemAndTry(dsq)) { auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint); if (!dmn) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::JoinExistingQueue -- dsq masternode is not in masternode list, masternode=%s\n", dsq.masternodeOutpoint.ToStringShort()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::JoinExistingQueue -- dsq masternode is not in masternode list, masternode=%s\n", dsq.masternodeOutpoint.ToStringShort()); continue; } // skip next mn payments winners if (dmn->pdmnState->nLastPaidHeight + nWeightedMnCount < mnList.GetHeight() + WinnersToSkip()) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::JoinExistingQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::JoinExistingQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString()); continue; } @@ -1077,20 +1075,20 @@ bool CCoinJoinClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, // in order for dsq to get into vecCoinJoinQueue, so we should be safe to mix already, // no need for additional verification here - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::JoinExistingQueue -- trying queue: %s\n", dsq.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::JoinExistingQueue -- trying queue: %s\n", dsq.ToString()); std::vector vecTxDSInTmp; // Try to match their denominations if possible, select exact number of denominations - if (!mixingWallet.SelectTxDSInsByDenomination(dsq.nDenom, nBalanceNeedsAnonymized, vecTxDSInTmp)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::JoinExistingQueue -- Couldn't match denomination %d (%s)\n", dsq.nDenom, CCoinJoin::DenominationToString(dsq.nDenom)); + if (!m_wallet.SelectTxDSInsByDenomination(dsq.nDenom, nBalanceNeedsAnonymized, vecTxDSInTmp)) { + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::JoinExistingQueue -- Couldn't match denomination %d (%s)\n", dsq.nDenom, CCoinJoin::DenominationToString(dsq.nDenom)); continue; } - coinJoinClientManagers.at(mixingWallet.GetName())->AddUsedMasternode(dsq.masternodeOutpoint); + m_manager.AddUsedMasternode(dsq.masternodeOutpoint); if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString()); continue; } @@ -1100,7 +1098,7 @@ bool CCoinJoinClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, connman.AddPendingMasternode(dmn->proTxHash); SetState(POOL_STATE_QUEUE); nTimeLastSuccessfulStep = GetTime(); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::JoinExistingQueue -- pending connection (from queue): nSessionDenom: %d (%s), addr=%s\n", + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::JoinExistingQueue -- pending connection (from queue): nSessionDenom: %d (%s), addr=%s\n", nSessionDenom, CCoinJoin::DenominationToString(nSessionDenom), dmn->pdmnState->addr.ToString()); strAutoDenomResult = _("Trying to connect..."); return true; @@ -1121,28 +1119,27 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon // find available denominated amounts std::set setAmounts; - if (!mixingWallet.SelectDenominatedAmounts(nBalanceNeedsAnonymized, setAmounts)) { + if (!m_wallet.SelectDenominatedAmounts(nBalanceNeedsAnonymized, setAmounts)) { // this should never happen strAutoDenomResult = _("Can't mix: no compatible inputs found!"); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::StartNewQueue -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- %s\n", strAutoDenomResult.original); return false; } // otherwise, try one randomly while (nTries < 10) { - auto dmn = coinJoinClientManagers.at(mixingWallet.GetName())->GetRandomNotUsedMasternode(); - + auto dmn = m_manager.GetRandomNotUsedMasternode(); if (!dmn) { strAutoDenomResult = _("Can't find random Masternode."); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::StartNewQueue -- %s\n", strAutoDenomResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- %s\n", strAutoDenomResult.original); return false; } - coinJoinClientManagers.at(mixingWallet.GetName())->AddUsedMasternode(dmn->collateralOutpoint); + m_manager.AddUsedMasternode(dmn->collateralOutpoint); // skip next mn payments winners if (dmn->pdmnState->nLastPaidHeight + nWeightedMnCount < mnList.GetHeight() + WinnersToSkip()) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::StartNewQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString()); nTries++; continue; } @@ -1150,7 +1147,7 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon int64_t nLastDsq = mmetaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq(); int64_t nDsqThreshold = mmetaman.GetDsqThreshold(dmn->proTxHash, nMnCount); if (nLastDsq != 0 && nDsqThreshold > mmetaman.GetDsqCount()) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::StartNewQueue -- Too early to mix on this masternode!" /* Continued */ + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- Too early to mix on this masternode!" /* Continued */ " masternode=%s addr=%s nLastDsq=%d nDsqThreshold=%d nDsqCount=%d\n", dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToString(), nLastDsq, nDsqThreshold, mmetaman.GetDsqCount()); @@ -1159,12 +1156,12 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon } if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString()); nTries++; continue; } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, dmn->pdmnState->addr.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, dmn->pdmnState->addr.ToString()); // try to get a single random denom out of setAmounts while (nSessionDenom == 0) { @@ -1180,7 +1177,7 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CCoinJoinAccept(nSessionDenom, txMyCollateral)); SetState(POOL_STATE_QUEUE); nTimeLastSuccessfulStep = GetTime(); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::StartNewQueue -- pending connection, nSessionDenom: %d (%s), addr=%s\n", + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- pending connection, nSessionDenom: %d (%s), addr=%s\n", nSessionDenom, CCoinJoin::DenominationToString(nSessionDenom), dmn->pdmnState->addr.ToString()); strAutoDenomResult = _("Trying to connect..."); return true; @@ -1194,7 +1191,7 @@ bool CCoinJoinClientSession::ProcessPendingDsaRequest(CConnman& connman) if (!pendingDsaRequest) return false; bool fDone = connman.ForNode(pendingDsaRequest.GetAddr(), [this, &connman](CNode* pnode) { - WalletCJLogPrint(mixingWallet, "-- processing dsa queue for addr=%s\n", pnode->addr.ToString()); + WalletCJLogPrint(m_wallet, "-- processing dsa queue for addr=%s\n", pnode->addr.ToString()); nTimeLastSuccessfulStep = GetTime(); CNetMsgMaker msgMaker(pnode->GetSendVersion()); connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSACCEPT, pendingDsaRequest.GetDSA())); @@ -1204,7 +1201,7 @@ bool CCoinJoinClientSession::ProcessPendingDsaRequest(CConnman& connman) if (fDone) { pendingDsaRequest = CPendingDsaRequest(); } else if (pendingDsaRequest.IsExpired()) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- failed to connect to %s\n", __func__, pendingDsaRequest.GetAddr().ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- failed to connect to %s\n", __func__, pendingDsaRequest.GetAddr().ToString()); WITH_LOCK(cs_coinjoin, SetNull()); } @@ -1252,14 +1249,14 @@ bool CCoinJoinClientManager::MarkAlreadyJoinedQueueAsTried(CCoinJoinQueue& dsq) bool CCoinJoinClientSession::SubmitDenominate(CConnman& connman) { - LOCK(mixingWallet.cs_wallet); + LOCK(m_wallet.cs_wallet); std::string strError; std::vector vecTxDSIn; std::vector > vecPSInOutPairsTmp; if (!SelectDenominate(strError, vecTxDSIn)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::SubmitDenominate -- SelectDenominate failed, error: %s\n", strError); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SubmitDenominate -- SelectDenominate failed, error: %s\n", strError); return false; } @@ -1267,10 +1264,10 @@ bool CCoinJoinClientSession::SubmitDenominate(CConnman& connman) for (const auto i : irange::range(CCoinJoinClientOptions::GetRounds() + CCoinJoinClientOptions::GetRandomRounds())) { if (PrepareDenominate(i, i, strError, vecTxDSIn, vecPSInOutPairsTmp, true)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for %d rounds, success\n", i); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for %d rounds, success\n", i); vecInputsByRounds.emplace_back(i, vecPSInOutPairsTmp.size()); } else { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for %d rounds, error: %s\n", i, strError); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for %d rounds, error: %s\n", i, strError); } } @@ -1279,25 +1276,25 @@ bool CCoinJoinClientSession::SubmitDenominate(CConnman& connman) return a.second > b.second || (a.second == b.second && a.first < b.first); }); - WalletCJLogPrint(mixingWallet, "vecInputsByRounds for denom %d\n", nSessionDenom); + WalletCJLogPrint(m_wallet, "vecInputsByRounds for denom %d\n", nSessionDenom); for (const auto& pair : vecInputsByRounds) { - WalletCJLogPrint(mixingWallet, "vecInputsByRounds: rounds: %d, inputs: %d\n", pair.first, pair.second); + WalletCJLogPrint(m_wallet, "vecInputsByRounds: rounds: %d, inputs: %d\n", pair.first, pair.second); } int nRounds = vecInputsByRounds.begin()->first; if (PrepareDenominate(nRounds, nRounds, strError, vecTxDSIn, vecPSInOutPairsTmp)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for %d rounds, success\n", nRounds); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for %d rounds, success\n", nRounds); return SendDenominate(vecPSInOutPairsTmp, connman); } // We failed? That's strange but let's just make final attempt and try to mix everything if (PrepareDenominate(0, CCoinJoinClientOptions::GetRounds() - 1, strError, vecTxDSIn, vecPSInOutPairsTmp)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for all rounds, success\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for all rounds, success\n"); return SendDenominate(vecPSInOutPairsTmp, connman); } // Should never actually get here but just in case - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for all rounds, error: %s\n", strError); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for all rounds, error: %s\n", strError); strAutoDenomResult = Untranslated(strError); return false; } @@ -1306,7 +1303,7 @@ bool CCoinJoinClientSession::SelectDenominate(std::string& strErrorRet, std::vec { if (!CCoinJoinClientOptions::IsEnabled()) return false; - if (mixingWallet.IsLocked(true)) { + if (m_wallet.IsLocked(true)) { strErrorRet = "Wallet locked, unable to create transaction!"; return false; } @@ -1318,7 +1315,7 @@ bool CCoinJoinClientSession::SelectDenominate(std::string& strErrorRet, std::vec vecTxDSInRet.clear(); - bool fSelected = mixingWallet.SelectTxDSInsByDenomination(nSessionDenom, CCoinJoin::GetMaxPoolAmount(), vecTxDSInRet); + bool fSelected = m_wallet.SelectTxDSInsByDenomination(nSessionDenom, CCoinJoin::GetMaxPoolAmount(), vecTxDSInRet); if (!fSelected) { strErrorRet = "Can't select current denominated inputs"; return false; @@ -1329,7 +1326,7 @@ bool CCoinJoinClientSession::SelectDenominate(std::string& strErrorRet, std::vec bool CCoinJoinClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, const std::vector& vecTxDSIn, std::vector >& vecPSInOutPairsRet, bool fDryRun) { - AssertLockHeld(mixingWallet.cs_wallet); + AssertLockHeld(m_wallet.cs_wallet); if (!CCoinJoin::IsValidDenomination(nSessionDenom)) { strErrorRet = "Incorrect session denom"; @@ -1359,7 +1356,7 @@ bool CCoinJoinClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds, s ++nSteps; continue; } - const auto pwallet = GetWallet(mixingWallet.GetName()); + const auto pwallet = GetWallet(m_wallet.GetName()); if (!pwallet) { strErrorRet ="Couldn't get wallet pointer"; return false; @@ -1382,7 +1379,7 @@ bool CCoinJoinClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds, s } for (const auto& [txDsIn, txDsOut] : vecPSInOutPairsRet) { - mixingWallet.LockCoin(txDsIn.prevout); + m_wallet.LockCoin(txDsIn.prevout); vecOutPointLocked.push_back(txDsIn.prevout); } @@ -1394,15 +1391,15 @@ bool CCoinJoinClientSession::MakeCollateralAmounts(const CBlockPolicyEstimator& { if (!CCoinJoinClientOptions::IsEnabled()) return false; - LOCK(mixingWallet.cs_wallet); + LOCK(m_wallet.cs_wallet); // NOTE: We do not allow txes larger than 100 kB, so we have to limit number of inputs here. // We still want to consume a lot of inputs to avoid creating only smaller denoms though. // Knowing that each CTxIn is at least 148 B big, 400 inputs should take 400 x ~148 B = ~60 kB. // This still leaves more than enough room for another data of typical MakeCollateralAmounts tx. - std::vector vecTally = mixingWallet.SelectCoinsGroupedByAddresses(false, false, true, 400); + std::vector vecTally = m_wallet.SelectCoinsGroupedByAddresses(false, false, true, 400); if (vecTally.empty()) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::MakeCollateralAmounts -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::MakeCollateralAmounts -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); return false; } @@ -1424,14 +1421,14 @@ bool CCoinJoinClientSession::MakeCollateralAmounts(const CBlockPolicyEstimator& } // If we got here then something is terribly broken actually - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::MakeCollateralAmounts -- ERROR: Can't make collaterals!\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::MakeCollateralAmounts -- ERROR: Can't make collaterals!\n"); return false; } // Split up large inputs or create fee sized inputs bool CCoinJoinClientSession::MakeCollateralAmounts(const CBlockPolicyEstimator& fee_estimator, const CompactTallyItem& tallyItem, bool fTryDenominated) { - AssertLockHeld(mixingWallet.cs_wallet); + AssertLockHeld(m_wallet.cs_wallet); if (!CCoinJoinClientOptions::IsEnabled()) return false; @@ -1445,16 +1442,16 @@ bool CCoinJoinClientSession::MakeCollateralAmounts(const CBlockPolicyEstimator& return false; } - const auto pwallet = GetWallet(mixingWallet.GetName()); + const auto pwallet = GetWallet(m_wallet.GetName()); if (!pwallet) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- Couldn't get wallet pointer\n", __func__); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- Couldn't get wallet pointer\n", __func__); return false; } CTransactionBuilder txBuilder(pwallet, tallyItem, fee_estimator); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- Start %s\n", __func__, txBuilder.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- Start %s\n", __func__, txBuilder.ToString()); // Skip way too tiny amounts. Smallest we want is minimum collateral amount in a one output tx if (!txBuilder.CouldAddOutput(CCoinJoin::GetCollateralAmount())) { @@ -1504,32 +1501,32 @@ bool CCoinJoinClientSession::MakeCollateralAmounts(const CBlockPolicyEstimator& assert(CCoinJoin::IsCollateralAmount(out->GetAmount())); } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- Done with case %d: %s\n", __func__, nCase, txBuilder.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- Done with case %d: %s\n", __func__, nCase, txBuilder.ToString()); assert(txBuilder.IsDust(txBuilder.GetAmountLeft())); bilingual_str strResult; if (!txBuilder.Commit(strResult)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- Commit failed: %s\n", __func__, strResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- Commit failed: %s\n", __func__, strResult.original); return false; } - coinJoinClientManagers.at(mixingWallet.GetName())->UpdatedSuccessBlock(); + m_manager.UpdatedSuccessBlock(); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- txid: %s\n", __func__, strResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- txid: %s\n", __func__, strResult.original); return true; } bool CCoinJoinClientSession::CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason) { - AssertLockHeld(mixingWallet.cs_wallet); + AssertLockHeld(m_wallet.cs_wallet); std::vector vCoins; CCoinControl coin_control; coin_control.nCoinType = CoinType::ONLY_COINJOIN_COLLATERAL; - mixingWallet.AvailableCoins(vCoins, true, &coin_control); + m_wallet.AvailableCoins(vCoins, true, &coin_control); if (vCoins.empty()) { strReason = strprintf("%s requires a collateral transaction and could not locate an acceptable input!", gCoinJoinName); @@ -1550,7 +1547,7 @@ bool CCoinJoinClientSession::CreateCollateralTransaction(CMutableTransaction& tx // make our change address CScript scriptChange; CTxDestination dest; - ReserveDestination reserveDest(&mixingWallet); + ReserveDestination reserveDest(&m_wallet); bool success = reserveDest.GetReservedDestination(dest, true); assert(success); // should never fail, as we just unlocked scriptChange = GetScriptForDestination(dest); @@ -1562,7 +1559,7 @@ bool CCoinJoinClientSession::CreateCollateralTransaction(CMutableTransaction& tx txCollateral.vout.emplace_back(0, CScript() << OP_RETURN); } - if (!mixingWallet.SignTransaction(txCollateral)) { + if (!m_wallet.SignTransaction(txCollateral)) { strReason = "Unable to sign collateral transaction!"; return false; } @@ -1575,15 +1572,15 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima { if (!CCoinJoinClientOptions::IsEnabled()) return false; - LOCK(mixingWallet.cs_wallet); + LOCK(m_wallet.cs_wallet); // NOTE: We do not allow txes larger than 100 kB, so we have to limit number of inputs here. // We still want to consume a lot of inputs to avoid creating only smaller denoms though. // Knowing that each CTxIn is at least 148 B big, 400 inputs should take 400 x ~148 B = ~60 kB. // This still leaves more than enough room for another data of typical CreateDenominated tx. - std::vector vecTally = mixingWallet.SelectCoinsGroupedByAddresses(true, true, true, 400); + std::vector vecTally = m_wallet.SelectCoinsGroupedByAddresses(true, true, true, 400); if (vecTally.empty()) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::CreateDenominated -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::CreateDenominated -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); return false; } @@ -1592,21 +1589,21 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima return a.nAmount > b.nAmount; }); - bool fCreateMixingCollaterals = !mixingWallet.HasCollateralInputs(); + bool fCreateMixingCollaterals = !m_wallet.HasCollateralInputs(); for (const auto& item : vecTally) { if (!CreateDenominated(fee_estimator, nBalanceToDenominate, item, fCreateMixingCollaterals)) continue; return true; } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::CreateDenominated -- failed!\n"); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::CreateDenominated -- failed!\n"); return false; } // Create denominations bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals) { - AssertLockHeld(mixingWallet.cs_wallet); + AssertLockHeld(m_wallet.cs_wallet); if (!CCoinJoinClientOptions::IsEnabled()) return false; @@ -1615,21 +1612,21 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima return false; } - const auto pwallet = GetWallet(mixingWallet.GetName()); + const auto pwallet = GetWallet(m_wallet.GetName()); if (!pwallet) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- Couldn't get wallet pointer\n", __func__); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- Couldn't get wallet pointer\n", __func__); return false; } CTransactionBuilder txBuilder(pwallet, tallyItem, fee_estimator); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- Start %s\n", __func__, txBuilder.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- Start %s\n", __func__, txBuilder.ToString()); // ****** Add an output for mixing collaterals ************ / if (fCreateMixingCollaterals && !txBuilder.AddOutput(CCoinJoin::GetMaxCollateralAmount())) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- Failed to add collateral output\n", __func__); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- Failed to add collateral output\n", __func__); return false; } @@ -1640,7 +1637,7 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima std::map mapDenomCount; for (auto nDenomValue : denoms) { - mapDenomCount.insert(std::pair(nDenomValue, mixingWallet.CountInputsWithAmount(nDenomValue))); + mapDenomCount.insert(std::pair(nDenomValue, m_wallet.CountInputsWithAmount(nDenomValue))); } // Will generate outputs for the createdenoms up to coinjoinmaxdenoms per denom @@ -1664,7 +1661,7 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima if (txBuilder.CouldAddOutput(nDenomValue)) { if (fAddFinal && nBalanceToDenominate > 0 && nBalanceToDenominate < nDenomValue) { fAddFinal = false; // add final denom only once, only the smalest possible one - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 1 - FINAL - nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 1 - FINAL - nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", strFunc, (float) nDenomValue / COIN, (float) nBalanceToDenominate / COIN, nOutputs, txBuilder.ToString()); return true; } else if (nBalanceToDenominate >= nDenomValue) { @@ -1681,10 +1678,10 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima ++nOutputs; ++currentDenomIt->second; nBalanceToDenominate -= nDenomValue; - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 1 - nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 1 - nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", __func__, (float) nDenomValue / COIN, (float) nBalanceToDenominate / COIN, nOutputs, txBuilder.ToString()); } else { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 1 - Error: AddOutput failed for nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 1 - Error: AddOutput failed for nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", __func__, (float) nDenomValue / COIN, (float) nBalanceToDenominate / COIN, nOutputs, txBuilder.ToString()); return false; } @@ -1700,11 +1697,11 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima // denom and that our nValueLeft/nBalanceToDenominate is enough to create one of these denoms, if so, loop again. if (count < CCoinJoinClientOptions::GetDenomsGoal() && txBuilder.CouldAddOutput(denom) && nBalanceToDenominate > 0) { finished = false; - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 1 - NOT finished - nDenomValue: %f, count: %d, nBalanceToDenominate: %f, %s\n", + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 1 - NOT finished - nDenomValue: %f, count: %d, nBalanceToDenominate: %f, %s\n", __func__, (float) denom / COIN, count, (float) nBalanceToDenominate / COIN, txBuilder.ToString()); break; } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 1 - FINISHED - nDenomValue: %f, count: %d, nBalanceToDenominate: %f, %s\n", + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 1 - FINISHED - nDenomValue: %f, count: %d, nBalanceToDenominate: %f, %s\n", __func__, (float) denom / COIN, count, (float) nBalanceToDenominate / COIN, txBuilder.ToString()); } @@ -1715,7 +1712,7 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima if (txBuilder.CouldAddOutput(CCoinJoin::GetSmallestDenomination()) && nBalanceToDenominate >= CCoinJoin::GetSmallestDenomination() && txBuilder.CountOutputs() < COINJOIN_DENOM_OUTPUTS_THRESHOLD) { CAmount nLargestDenomValue = denoms.front(); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 2 - Process remainder: %s\n", __func__, txBuilder.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 2 - Process remainder: %s\n", __func__, txBuilder.ToString()); auto countPossibleOutputs = [&](CAmount nAmount) -> int { std::vector vecOutputs; @@ -1749,7 +1746,7 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima int denomsToCreateBal = (nBalanceToDenominate / nDenomValue) + 1; // Use the smaller value int denomsToCreate = denomsToCreateValue > denomsToCreateBal ? denomsToCreateBal : denomsToCreateValue; - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 2 - nBalanceToDenominate: %f, nDenomValue: %f, denomsToCreateValue: %d, denomsToCreateBal: %d\n", + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 2 - nBalanceToDenominate: %f, nDenomValue: %f, denomsToCreateValue: %d, denomsToCreateBal: %d\n", __func__, (float) nBalanceToDenominate / COIN, (float) nDenomValue / COIN, denomsToCreateValue, denomsToCreateBal); auto it = mapDenomCount.find(nDenomValue); for (const auto i : irange::range(denomsToCreate)) { @@ -1762,10 +1759,10 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima it->second++; nBalanceToDenominate -= nDenomValue; } else { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 2 - Error: AddOutput failed at %d/%d, %s\n", __func__, i + 1, denomsToCreate, txBuilder.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 2 - Error: AddOutput failed at %d/%d, %s\n", __func__, i + 1, denomsToCreate, txBuilder.ToString()); break; } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 2 - nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 2 - nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", __func__, (float) nDenomValue / COIN, (float) nBalanceToDenominate / COIN, nOutputs, txBuilder.ToString()); if (txBuilder.CountOutputs() >= COINJOIN_DENOM_OUTPUTS_THRESHOLD) break; } @@ -1773,10 +1770,10 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima } } - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 3 - nBalanceToDenominate: %f, %s\n", __func__, (float) nBalanceToDenominate / COIN, txBuilder.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 3 - nBalanceToDenominate: %f, %s\n", __func__, (float) nBalanceToDenominate / COIN, txBuilder.ToString()); for (const auto [denom, count] : mapDenomCount) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- 3 - DONE - nDenomValue: %f, count: %d\n", __func__, (float) denom / COIN, count); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- 3 - DONE - nDenomValue: %f, count: %d\n", __func__, (float) denom / COIN, count); } // No reasons to create mixing collaterals if we can't create denoms to mix @@ -1786,14 +1783,14 @@ bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estima bilingual_str strResult; if (!txBuilder.Commit(strResult)) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- Commit failed: %s\n", __func__, strResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- Commit failed: %s\n", __func__, strResult.original); return false; } // use the same nCachedLastSuccessBlock as for DS mixing to prevent race - coinJoinClientManagers.at(mixingWallet.GetName())->UpdatedSuccessBlock(); + m_manager.UpdatedSuccessBlock(); - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::%s -- txid: %s\n", __func__, strResult.original); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- txid: %s\n", __func__, strResult.original); return true; } @@ -1803,7 +1800,7 @@ void CCoinJoinClientSession::RelayIn(const CCoinJoinEntry& entry, CConnman& conn if (!mixingMasternode) return; connman.ForNode(mixingMasternode->pdmnState->addr, [&entry, &connman, this](CNode* pnode) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::RelayIn -- found master, relaying message to %s\n", pnode->addr.ToString()); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::RelayIn -- found master, relaying message to %s\n", pnode->addr.ToString()); CNetMsgMaker msgMaker(pnode->GetSendVersion()); connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSVIN, entry)); return true; @@ -1812,14 +1809,14 @@ void CCoinJoinClientSession::RelayIn(const CCoinJoinEntry& entry, CConnman& conn void CCoinJoinClientSession::SetState(PoolState nStateNew) { - WalletCJLogPrint(mixingWallet, "CCoinJoinClientSession::SetState -- nState: %d, nStateNew: %d\n", nState.load(), nStateNew); + WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SetState -- nState: %d, nStateNew: %d\n", nState.load(), nStateNew); nState = nStateNew; } void CCoinJoinClientManager::UpdatedBlockTip(const CBlockIndex* pindex) { nCachedBlockHeight = pindex->nHeight; - WalletCJLogPrint(mixingWallet, "CCoinJoinClientManager::UpdatedBlockTip -- nCachedBlockHeight: %d\n", nCachedBlockHeight); + WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::UpdatedBlockTip -- nCachedBlockHeight: %d\n", nCachedBlockHeight); } void CCoinJoinClientQueueManager::DoMaintenance() @@ -1882,13 +1879,15 @@ void CCoinJoinClientManager::GetJsonInfo(UniValue& obj) const obj.pushKV("sessions", arrSessions); } -void DoCoinJoinMaintenance(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool) -{ - if (coinJoinClientQueueManager != nullptr) { - coinJoinClientQueueManager->DoMaintenance(); - } +void CJClientManager::Add(CWallet& wallet) { + m_wallet_manager_map.try_emplace( + wallet.GetName(), + std::make_unique(wallet, *this, m_mn_sync, m_queueman) + ); +} - for (const auto& pair : coinJoinClientManagers) { - pair.second->DoMaintenance(connman, fee_estimator, mempool); +void CJClientManager::DoMaintenance(CBlockPolicyEstimator& fee_estimator) { + for (auto& [wallet_str, clientman] : m_wallet_manager_map) { + clientman->DoMaintenance(m_connman, fee_estimator, m_mempool); } } diff --git a/src/coinjoin/client.h b/src/coinjoin/client.h index e336475bc2..65ebbb88c5 100644 --- a/src/coinjoin/client.h +++ b/src/coinjoin/client.h @@ -7,33 +7,31 @@ #include #include +#include #include #include #include +#include #include -class CDeterministicMN; -using CDeterministicMNCPtr = std::shared_ptr; - +class CBlockPolicyEstimator; class CCoinJoinClientManager; class CCoinJoinClientQueueManager; - -class CBlockPolicyEstimator; class CConnman; +class CDeterministicMN; +class CJClientManager; class CNode; +class CMasternodeSync; class CTxMemPool; class PeerManager; class UniValue; -class CMasternodeSync; +using CDeterministicMNCPtr = std::shared_ptr; // The main object for accessing mixing -extern std::map> coinJoinClientManagers; - -// The object to track mixing queues -extern std::unique_ptr coinJoinClientQueueManager; +extern std::unique_ptr coinJoinClientManagers; class CPendingDsaRequest { @@ -72,10 +70,53 @@ public: } }; +class CJClientManager { +public: + using wallet_name_cjman_map = std::map>; + +public: + CJClientManager(CConnman& connman, CTxMemPool& mempool, const CMasternodeSync& mn_sync, + const std::unique_ptr& queueman) + : m_connman(connman), m_mempool(mempool), m_mn_sync(mn_sync), m_queueman(queueman) {} + ~CJClientManager() { + for (auto& [wallet_name, cj_man] : m_wallet_manager_map) { + cj_man.reset(); + } + } + + void Add(CWallet& wallet); + void DoMaintenance(CBlockPolicyEstimator& fee_estimator); + + void Remove(const std::string& name) { + m_wallet_manager_map.erase(name); + } + + CCoinJoinClientManager* Get(const CWallet& wallet) const { + auto it = m_wallet_manager_map.find(wallet.GetName()); + return (it != m_wallet_manager_map.end()) ? it->second.get() : nullptr; + } + + const wallet_name_cjman_map& raw() const { return m_wallet_manager_map; } + +private: + CConnman& m_connman; + CTxMemPool& m_mempool; + + const CMasternodeSync& m_mn_sync; + const std::unique_ptr& m_queueman; + + wallet_name_cjman_map m_wallet_manager_map; +}; + class CCoinJoinClientSession : public CCoinJoinBaseSession { private: + CWallet& m_wallet; + CJClientManager& m_clientman; + CCoinJoinClientManager& m_manager; + const CMasternodeSync& m_mn_sync; + const std::unique_ptr& m_queueman; std::vector vecOutPointLocked; @@ -88,8 +129,6 @@ private: CKeyHolderStorage keyHolderStorage; // storage for keys used in PrepareDenominate - CWallet& mixingWallet; - /// Create denominations bool CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate); bool CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals); @@ -125,10 +164,9 @@ private: void SetNull() EXCLUSIVE_LOCKS_REQUIRED(cs_coinjoin); public: - explicit CCoinJoinClientSession(CWallet& pwallet, const CMasternodeSync& mn_sync) : - m_mn_sync(mn_sync), mixingWallet(pwallet) - { - } + explicit CCoinJoinClientSession(CWallet& pwallet, CJClientManager& clientman, const CMasternodeSync& mn_sync, + const std::unique_ptr& queueman) : + m_wallet(pwallet), m_clientman(clientman), m_manager(*Assert(clientman.Get(pwallet))), m_mn_sync(mn_sync), m_queueman(queueman) {} void ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv); @@ -159,12 +197,13 @@ class CCoinJoinClientQueueManager : public CCoinJoinBaseManager { private: CConnman& connman; + CJClientManager& m_clientman; const CMasternodeSync& m_mn_sync; mutable Mutex cs_ProcessDSQueue; public: - explicit CCoinJoinClientQueueManager(CConnman& _connman, const CMasternodeSync& mn_sync) : - connman(_connman), m_mn_sync(mn_sync) {}; + explicit CCoinJoinClientQueueManager(CConnman& _connman, CJClientManager& clientman, const CMasternodeSync& mn_sync) : + connman(_connman), m_clientman(clientman), m_mn_sync(mn_sync) {}; void ProcessMessage(const CNode& peer, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); void ProcessDSQueue(const CNode& peer, PeerManager& peerman, CDataStream& vRecv); @@ -176,10 +215,14 @@ public: class CCoinJoinClientManager { private: - // Keep track of the used Masternodes - std::vector vecMasternodesUsed; + CWallet& m_wallet; + CJClientManager& m_clientman; const CMasternodeSync& m_mn_sync; + const std::unique_ptr& m_queueman; + + // Keep track of the used Masternodes + std::vector vecMasternodesUsed; mutable Mutex cs_deqsessions; // TODO: or map ?? @@ -191,8 +234,6 @@ private: int nMinBlocksToWait{1}; // how many blocks to wait for after one successful mixing tx in non-multisession mode bilingual_str strAutoDenomResult; - CWallet& mixingWallet; - // Keep track of current block height int nCachedBlockHeight{0}; @@ -209,8 +250,9 @@ public: CCoinJoinClientManager(CCoinJoinClientManager const&) = delete; CCoinJoinClientManager& operator=(CCoinJoinClientManager const&) = delete; - explicit CCoinJoinClientManager(CWallet& wallet, const CMasternodeSync& mn_sync) : - m_mn_sync(mn_sync), mixingWallet(wallet) {} + explicit CCoinJoinClientManager(CWallet& wallet, CJClientManager& clientman, const CMasternodeSync& mn_sync, + const std::unique_ptr& queueman) : + m_wallet(wallet), m_clientman(clientman), m_mn_sync(mn_sync), m_queueman(queueman) {} void ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_deqsessions); @@ -246,7 +288,4 @@ public: void GetJsonInfo(UniValue& obj) const LOCKS_EXCLUDED(cs_deqsessions); }; - -void DoCoinJoinMaintenance(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool); - #endif // BITCOIN_COINJOIN_CLIENT_H diff --git a/src/coinjoin/context.cpp b/src/coinjoin/context.cpp new file mode 100644 index 0000000000..4e8c725320 --- /dev/null +++ b/src/coinjoin/context.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2023 The Dash Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include + +#ifdef ENABLE_WALLET +#include +#endif // ENABLE_WALLET +#include + +CJContext::CJContext(CChainState& chainstate, CConnman& connman, CTxMemPool& mempool, const CMasternodeSync& mn_sync, bool relay_txes) : +#ifdef ENABLE_WALLET + clientman { + [&]() -> CJClientManager* const { + assert(::coinJoinClientManagers == nullptr); + ::coinJoinClientManagers = std::make_unique(connman, mempool, mn_sync, queueman); + return ::coinJoinClientManagers.get(); + }() + }, + queueman {relay_txes ? std::make_unique(connman, *clientman, mn_sync) : nullptr}, +#endif // ENABLE_WALLET + server{std::make_unique(chainstate, connman, mempool, mn_sync)} +{} + +CJContext::~CJContext() { +#ifdef ENABLE_WALLET + ::coinJoinClientManagers.reset(); +#endif // ENABLE_WALLET +} diff --git a/src/coinjoin/context.h b/src/coinjoin/context.h new file mode 100644 index 0000000000..d05da33e3c --- /dev/null +++ b/src/coinjoin/context.h @@ -0,0 +1,39 @@ +// Copyright (c) 2023 The Dash Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_COINJOIN_CONTEXT_H +#define BITCOIN_COINJOIN_CONTEXT_H + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include + +class CBlockPolicyEstimator; +class CChainState; +class CCoinJoinServer; +class CConnman; +class CMasternodeSync; +class CTxMemPool; + +#ifdef ENABLE_WALLET +class CCoinJoinClientQueueManager; +class CJClientManager; +#endif // ENABLE_WALLET + +struct CJContext { + CJContext() = delete; + CJContext(const CJContext&) = delete; + CJContext(CChainState& chainstate, CConnman& connman, CTxMemPool& mempool, const CMasternodeSync& mn_sync, bool relay_txes); + ~CJContext(); + +#ifdef ENABLE_WALLET + CJClientManager* const clientman; + const std::unique_ptr queueman; +#endif // ENABLE_WALLET + const std::unique_ptr server; +}; + +#endif // BITCOIN_COINJOIN_CONTEXT_H diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index 382e95d7eb..5eae338f69 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -23,7 +23,6 @@ #include -std::unique_ptr coinJoinServer; constexpr static CAmount DEFAULT_MAX_RAW_TX_FEE{COIN / 10}; void CCoinJoinServer::ProcessMessage(CNode& peer, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv) @@ -886,17 +885,15 @@ void CCoinJoinServer::SetState(PoolState nStateNew) nState = nStateNew; } -void CCoinJoinServer::DoMaintenance() const +void CCoinJoinServer::DoMaintenance() { if (!fMasternodeMode) return; // only run on masternodes if (!m_mn_sync.IsBlockchainSynced()) return; if (ShutdownRequested()) return; - if (!coinJoinServer) return; - - coinJoinServer->CheckForCompleteQueue(); - coinJoinServer->CheckPool(); - coinJoinServer->CheckTimeout(); + CheckForCompleteQueue(); + CheckPool(); + CheckTimeout(); } void CCoinJoinServer::GetJsonInfo(UniValue& obj) const diff --git a/src/coinjoin/server.h b/src/coinjoin/server.h index c2e54aef61..de509019be 100644 --- a/src/coinjoin/server.h +++ b/src/coinjoin/server.h @@ -15,9 +15,6 @@ class PeerManager; class UniValue; -// The main object for accessing mixing -extern std::unique_ptr coinJoinServer; - /** Used to keep track of current status of mixing pool */ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager @@ -96,7 +93,7 @@ public: void CheckTimeout(); void CheckForCompleteQueue(); - void DoMaintenance() const; + void DoMaintenance(); void GetJsonInfo(UniValue& obj) const; }; diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 5e1d16635b..f32ee68c66 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -7,6 +7,7 @@ #ifdef ENABLE_WALLET #include #endif // ENABLE_WALLET +#include #include #include #include @@ -23,8 +24,9 @@ CDSNotificationInterface::CDSNotificationInterface(CConnman& _connman, CMasternodeSync& _mn_sync, const std::unique_ptr& _dmnman, - CGovernanceManager& _govman, const std::unique_ptr& _llmq_ctx -) : connman(_connman), m_mn_sync(_mn_sync), dmnman(_dmnman), govman(_govman), llmq_ctx(_llmq_ctx) {} + CGovernanceManager& _govman, const std::unique_ptr& _llmq_ctx, + const std::unique_ptr& _cj_ctx +) : connman(_connman), m_mn_sync(_mn_sync), dmnman(_dmnman), govman(_govman), llmq_ctx(_llmq_ctx), cj_ctx(_cj_ctx) {} void CDSNotificationInterface::InitializeCurrentBlockTip() { @@ -66,7 +68,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con CCoinJoin::UpdatedBlockTip(pindexNew, *llmq_ctx->clhandler, m_mn_sync); #ifdef ENABLE_WALLET - for (auto& pair : coinJoinClientManagers) { + for (auto& pair : cj_ctx->clientman->raw()) { pair.second->UpdatedBlockTip(pindexNew); } #endif // ENABLE_WALLET diff --git a/src/dsnotificationinterface.h b/src/dsnotificationinterface.h index b01bbdac9f..f3c0d8e1d2 100644 --- a/src/dsnotificationinterface.h +++ b/src/dsnotificationinterface.h @@ -11,6 +11,7 @@ class CConnman; class CDeterministicMNManager; class CGovernanceManager; class CMasternodeSync; +struct CJContext; struct LLMQContext; class CDSNotificationInterface : public CValidationInterface @@ -18,7 +19,8 @@ class CDSNotificationInterface : public CValidationInterface public: explicit CDSNotificationInterface(CConnman& _connman, CMasternodeSync& _mn_sync, const std::unique_ptr& _dmnman, - CGovernanceManager& _govman, const std::unique_ptr& _llmq_ctx); + CGovernanceManager& _govman, const std::unique_ptr& _llmq_ctx, + const std::unique_ptr& _cj_ctx); virtual ~CDSNotificationInterface() = default; // a small helper to initialize current block height in sub-modules on startup @@ -45,6 +47,7 @@ private: CGovernanceManager& govman; const std::unique_ptr& llmq_ctx; + const std::unique_ptr& cj_ctx; }; #endif // BITCOIN_DSNOTIFICATIONINTERFACE_H diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp index 4806650d5e..ae088b36c4 100644 --- a/src/dummywallet.cpp +++ b/src/dummywallet.cpp @@ -24,7 +24,7 @@ public: // Dash Specific WalletInitInterface InitCoinJoinSettings void AutoLockMasternodeCollaterals() const override {} - void InitCoinJoinSettings() const override {} + void InitCoinJoinSettings(const CJClientManager& clientman) const override {} bool InitAutoBackup() const override {return true;} }; @@ -74,7 +74,7 @@ const WalletInitInterface& g_wallet_init_interface = DummyWalletInit(); namespace interfaces { -std::unique_ptr MakeWallet(const std::shared_ptr& wallet) +std::unique_ptr MakeWallet(const std::shared_ptr& wallet, const CJClientManager& clientman) { throw std::logic_error("Wallet function called in non-wallet build."); } diff --git a/src/init.cpp b/src/init.cpp index ce51b74262..c5cfa05960 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -68,6 +68,7 @@ #include #include +#include #ifdef ENABLE_WALLET #include #include @@ -320,10 +321,6 @@ void PrepareShutdown(NodeContext& node) // After all scheduled tasks have been flushed, destroy pointers // and reset all to nullptr. - ::coinJoinServer.reset(); -#ifdef ENABLE_WALLET - ::coinJoinClientQueueManager.reset(); -#endif // ENABLE_WALLET ::governance.reset(); ::sporkManager.reset(); ::masternodeSync.reset(); @@ -393,6 +390,11 @@ void PrepareShutdown(NodeContext& node) } node.chain_clients.clear(); + + // After all wallets are removed, destroy all CoinJoin objects + // and reset them to nullptr + node.cj_ctx.reset(); + UnregisterAllValidationInterfaces(); GetMainSignals().UnregisterBackgroundSignalScheduler(); } @@ -1698,7 +1700,8 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc assert(!node.peerman); node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(), - *node.scheduler, chainman, *node.mempool, node.llmq_ctx, *::governance, ignores_incoming_txs); + *node.scheduler, chainman, *node.mempool, *::governance, + node.cj_ctx, node.llmq_ctx, ignores_incoming_txs); RegisterValidationInterface(node.peerman.get()); assert(!::sporkManager); @@ -1852,7 +1855,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc assert(masternodeSync != nullptr); assert(governance != nullptr); pdsNotificationInterface = new CDSNotificationInterface( - *node.connman, *::masternodeSync, ::deterministicMNManager, *::governance, node.llmq_ctx + *node.connman, *::masternodeSync, ::deterministicMNManager, *::governance, node.llmq_ctx, node.cj_ctx ); RegisterValidationInterface(pdsNotificationInterface); @@ -2191,6 +2194,14 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc return false; } + // ********************************************************* Step 7c: Setup CoinJoin + + node.cj_ctx = std::make_unique(chainman.ActiveChainstate(), *node.connman, *node.mempool, *::masternodeSync, !ignores_incoming_txs); + +#ifdef ENABLE_WALLET + g_wallet_init_interface.InitCoinJoinSettings(*node.cj_ctx->clientman); +#endif // ENABLE_WALLET + // ********************************************************* Step 8: start indexers if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { g_txindex = std::make_unique(nTxIndexCache, false, fReindex); @@ -2252,18 +2263,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc return false; } - // ********************************************************* Step 10a: Setup CoinJoin - - ::coinJoinServer = std::make_unique(chainman.ActiveChainstate(), *node.connman, *node.mempool, *::masternodeSync); -#ifdef ENABLE_WALLET - if (!ignores_incoming_txs) { - ::coinJoinClientQueueManager = std::make_unique(*node.connman, *::masternodeSync); - } -#endif // ENABLE_WALLET - - g_wallet_init_interface.InitCoinJoinSettings(); - - // ********************************************************* Step 10b: Load cache data + // ********************************************************* Step 10a: Load cache data // LOAD SERIALIZED DAT FILES INTO DATA CACHES FOR INTERNAL USE @@ -2318,7 +2318,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc node.scheduler->scheduleEvery(std::bind(&CNetFulfilledRequestManager::DoMaintenance, std::ref(netfulfilledman)), std::chrono::minutes{1}); node.scheduler->scheduleEvery(std::bind(&CMasternodeSync::DoMaintenance, std::ref(*::masternodeSync)), std::chrono::seconds{1}); - node.scheduler->scheduleEvery(std::bind(&CMasternodeUtils::DoMaintenance, std::ref(*node.connman), std::ref(*::masternodeSync)), std::chrono::minutes{1}); + node.scheduler->scheduleEvery(std::bind(&CMasternodeUtils::DoMaintenance, std::ref(*node.connman), std::ref(*::masternodeSync), std::ref(*node.cj_ctx)), std::chrono::minutes{1}); node.scheduler->scheduleEvery(std::bind(&CDeterministicMNManager::DoMaintenance, std::ref(*deterministicMNManager)), std::chrono::seconds{10}); if (!fDisableGovernance) { @@ -2326,11 +2326,12 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc } if (fMasternodeMode) { - node.scheduler->scheduleEvery(std::bind(&CCoinJoinServer::DoMaintenance, std::ref(*::coinJoinServer)), std::chrono::seconds{1}); + node.scheduler->scheduleEvery(std::bind(&CCoinJoinServer::DoMaintenance, std::ref(*node.cj_ctx->server)), std::chrono::seconds{1}); node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.llmq_ctx->qdkgsman)), std::chrono::hours{1}); #ifdef ENABLE_WALLET } else if (!ignores_incoming_txs) { - node.scheduler->scheduleEvery(std::bind(&DoCoinJoinMaintenance, std::ref(*node.connman), std::ref(*node.fee_estimator), std::ref(*node.mempool)), std::chrono::seconds{1}); + node.scheduler->scheduleEvery(std::bind(&CCoinJoinClientQueueManager::DoMaintenance, std::ref(*node.cj_ctx->queueman)), std::chrono::seconds{1}); + node.scheduler->scheduleEvery(std::bind(&CJClientManager::DoMaintenance, std::ref(*node.cj_ctx->clientman), std::ref(*node.fee_estimator)), std::chrono::seconds{1}); #endif // ENABLE_WALLET } diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index 7232bc79f6..734c8e0e99 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -26,6 +26,7 @@ class CCoinControl; class CFeeRate; +class CJClientManager; class CKey; class CWallet; enum class FeeReason; @@ -353,10 +354,10 @@ class WalletLoader : public ChainClient { public: //! Create new wallet. - virtual std::unique_ptr createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector& warnings) = 0; + virtual std::unique_ptr createWallet(const CJClientManager& client_man, const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector& warnings) = 0; //! Load existing wallet. - virtual std::unique_ptr loadWallet(const std::string& name, bilingual_str& error, std::vector& warnings) = 0; + virtual std::unique_ptr loadWallet(const CJClientManager& client_man, const std::string& name, bilingual_str& error, std::vector& warnings) = 0; //! Return default wallet directory. virtual std::string getWalletDir() = 0; @@ -454,7 +455,7 @@ struct WalletTxOut //! Return implementation of Wallet interface. This function is defined in //! dummywallet.cpp and throws if the wallet component is not compiled. -std::unique_ptr MakeWallet(const std::shared_ptr& wallet); +std::unique_ptr MakeWallet(const std::shared_ptr& wallet, const CJClientManager& clientman); //! Return implementation of ChainClient interface for a wallet loader. This //! function will be undefined in builds where ENABLE_WALLET is false. diff --git a/src/masternode/utils.cpp b/src/masternode/utils.cpp index a31d82d11c..03fba7cec6 100644 --- a/src/masternode/utils.cpp +++ b/src/masternode/utils.cpp @@ -13,16 +13,16 @@ #include #include #include +#include - -void CMasternodeUtils::DoMaintenance(CConnman& connman, const CMasternodeSync& mn_sync) +void CMasternodeUtils::DoMaintenance(CConnman& connman, const CMasternodeSync& mn_sync, const CJContext& cj_ctx) { if (!mn_sync.IsBlockchainSynced()) return; if (ShutdownRequested()) return; std::vector vecDmns; // will be empty when no wallet #ifdef ENABLE_WALLET - for (const auto& pair : coinJoinClientManagers) { + for (auto& pair : cj_ctx.clientman->raw()) { pair.second->GetMixingMasternodesInfo(vecDmns); } #endif // ENABLE_WALLET diff --git a/src/masternode/utils.h b/src/masternode/utils.h index 3437175d62..9ff6b0ed3a 100644 --- a/src/masternode/utils.h +++ b/src/masternode/utils.h @@ -7,11 +7,12 @@ class CConnman; class CMasternodeSync; +struct CJContext; class CMasternodeUtils { public: - static void DoMaintenance(CConnman &connman, const CMasternodeSync& mn_sync); + static void DoMaintenance(CConnman &connman, const CMasternodeSync& mn_sync, const CJContext& cj_ctx); }; #endif // BITCOIN_MASTERNODE_UTILS_H diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 2f2649ba70..46f4bb30e9 100755 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -44,6 +44,7 @@ #ifdef ENABLE_WALLET #include #endif // ENABLE_WALLET +#include #include #include @@ -220,7 +221,8 @@ class PeerManagerImpl final : public PeerManager public: PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, - CTxMemPool& pool, const std::unique_ptr& llmq_ctx, CGovernanceManager& govman, bool ignore_incoming_txs); + CTxMemPool& pool, CGovernanceManager& govman, const std::unique_ptr& cj_ctx, + const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); /** Overridden from CValidationInterface. */ void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexConnected) override; @@ -309,6 +311,7 @@ private: BanMan* const m_banman; ChainstateManager& m_chainman; CTxMemPool& m_mempool; + const std::unique_ptr& m_cj_ctx; const std::unique_ptr& m_llmq_ctx; CGovernanceManager& m_govman; @@ -1543,20 +1546,23 @@ bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex, const Conse std::unique_ptr PeerManager::make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, - const std::unique_ptr& llmq_ctx, CGovernanceManager& govman, bool ignore_incoming_txs) + CGovernanceManager& govman, const std::unique_ptr& cj_ctx, + const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) { - return std::make_unique(chainparams, connman, addrman, banman, scheduler, chainman, pool, llmq_ctx, govman, ignore_incoming_txs); + return std::make_unique(chainparams, connman, addrman, banman, scheduler, chainman, pool, govman, cj_ctx, llmq_ctx, ignore_incoming_txs); } PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, - const std::unique_ptr& llmq_ctx, CGovernanceManager& govman, bool ignore_incoming_txs) + CGovernanceManager& govman, const std::unique_ptr& cj_ctx, + const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) : m_chainparams(chainparams), m_connman(connman), m_addrman(addrman), m_banman(banman), m_chainman(chainman), m_mempool(pool), + m_cj_ctx(cj_ctx), m_llmq_ctx(llmq_ctx), m_govman(govman), m_stale_tip_check_time(0), @@ -4313,12 +4319,12 @@ void PeerManagerImpl::ProcessMessage( { //probably one the extensions #ifdef ENABLE_WALLET - coinJoinClientQueueManager->ProcessMessage(pfrom, *this, msg_type, vRecv); - for (auto& pair : coinJoinClientManagers) { + m_cj_ctx->queueman->ProcessMessage(pfrom, *this, msg_type, vRecv); + for (auto& pair : m_cj_ctx->clientman->raw()) { pair.second->ProcessMessage(pfrom, *this, m_connman, m_mempool, msg_type, vRecv); } #endif // ENABLE_WALLET - coinJoinServer->ProcessMessage(pfrom, *this, msg_type, vRecv); + m_cj_ctx->server->ProcessMessage(pfrom, *this, msg_type, vRecv); sporkManager->ProcessMessage(pfrom, *this, m_connman, msg_type, vRecv); ::masternodeSync->ProcessMessage(pfrom, msg_type, vRecv); m_govman.ProcessMessage(pfrom, *this, m_connman, msg_type, vRecv); diff --git a/src/net_processing.h b/src/net_processing.h index c29acec7cd..ed4865a697 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -15,6 +15,8 @@ class CAddrMan; class CTxMemPool; class ChainstateManager; +class CCoinJoinServer; +struct CJContext; struct LLMQContext; class CGovernanceManager; @@ -40,7 +42,8 @@ class PeerManager : public CValidationInterface, public NetEventsInterface public: static std::unique_ptr make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, - CTxMemPool& pool, const std::unique_ptr& llmq_ctx, CGovernanceManager& govman, bool ignore_incoming_txs); + CTxMemPool& pool, CGovernanceManager& govman, const std::unique_ptr& cj_ctx, + const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); virtual ~PeerManager() { } /** Get statistics from node state */ diff --git a/src/node/context.cpp b/src/node/context.cpp index ed3d4b9ac8..7772fcf8a3 100644 --- a/src/node/context.cpp +++ b/src/node/context.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include diff --git a/src/node/context.h b/src/node/context.h index f44cc8d51b..91ff6df05d 100644 --- a/src/node/context.h +++ b/src/node/context.h @@ -16,12 +16,14 @@ class CAddrMan; class CBlockPolicyEstimator; class CConnman; class CCreditPoolManager; +class ChainstateManager; +class CEvoDB; class CScheduler; class CTxMemPool; -class ChainstateManager; -struct LLMQContext; class PeerManager; -class CEvoDB; +struct CJContext; +struct LLMQContext; + namespace interfaces { class Chain; class ChainClient; @@ -58,6 +60,7 @@ struct NodeContext { //! Dash std::unique_ptr llmq_ctx; std::unique_ptr creditPoolManager; + std::unique_ptr cj_ctx; std::unique_ptr evodb; diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index f646419a6c..b5958ba75f 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -108,7 +109,8 @@ void TestAddAddressesToSendBook(interfaces::Node& node) OptionsModel optionsModel(node); ClientModel clientModel(node, &optionsModel); AddWallet(wallet); - WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel); + // TODO: replace access of CoinJoin objects with access through interface + WalletModel walletModel(interfaces::MakeWallet(wallet, *::coinJoinClientManagers), clientModel); RemoveWallet(wallet, std::nullopt); EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress); editAddressDialog.setModel(walletModel.getAddressTableModel()); diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 387479831e..23c58c9eed 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -135,7 +135,8 @@ void TestGUI(interfaces::Node& node) TransactionView transactionView; OptionsModel optionsModel(node); ClientModel clientModel(node, &optionsModel); - WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel);; + // TODO: replace access of CoinJoin objects with access through interface + WalletModel walletModel(interfaces::MakeWallet(wallet, *::coinJoinClientManagers), clientModel);; sendCoinsDialog.setModel(&walletModel); transactionView.setModel(&walletModel); diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index ddd2fd346a..0afbf282e0 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -228,7 +230,7 @@ void CreateWalletActivity::createWallet() } QTimer::singleShot(500, worker(), [this, name, flags] { - std::unique_ptr wallet = node().walletLoader().createWallet(name, m_passphrase, flags, m_error_message, m_warning_message); + std::unique_ptr wallet = node().walletLoader().createWallet(*::coinJoinClientManagers, name, m_passphrase, flags, m_error_message, m_warning_message); if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet)); @@ -299,7 +301,7 @@ void OpenWalletActivity::open(const std::string& path) showProgressDialog(tr("Opening Wallet %1...").arg(name.toHtmlEscaped())); QTimer::singleShot(0, worker(), [this, path] { - std::unique_ptr wallet = node().walletLoader().loadWallet(path, m_error_message, m_warning_message); + std::unique_ptr wallet = node().walletLoader().loadWallet(*::coinJoinClientManagers, path, m_error_message, m_warning_message); if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet)); diff --git a/src/rpc/coinjoin.cpp b/src/rpc/coinjoin.cpp index f3e6d2993a..2dd16529eb 100644 --- a/src/rpc/coinjoin.cpp +++ b/src/rpc/coinjoin.cpp @@ -4,17 +4,19 @@ #include #include -#ifdef ENABLE_WALLET -#include -#include -#include -#endif // ENABLE_WALLET +#include #include #include #include #include #include +#ifdef ENABLE_WALLET +#include +#include +#include +#endif // ENABLE_WALLET + #include #ifdef ENABLE_WALLET @@ -49,7 +51,8 @@ static UniValue coinjoin(const JSONRPCRequest& request) } } - auto it = coinJoinClientManagers.find(wallet->GetName()); + auto cj_clientman = ::coinJoinClientManagers->Get(*wallet); + CHECK_NONFATAL(cj_clientman != nullptr); if (request.params[0].get_str() == "start") { { @@ -58,24 +61,24 @@ static UniValue coinjoin(const JSONRPCRequest& request) throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please unlock wallet for mixing with walletpassphrase first."); } - if (!it->second->StartMixing()) { + if (!cj_clientman->StartMixing()) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Mixing has been started already."); } const NodeContext& node = EnsureAnyNodeContext(request.context); CTxMemPool& mempool = EnsureMemPool(node); CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(node); - bool result = it->second->DoAutomaticDenominating(*node.connman, fee_estimator, mempool); - return "Mixing " + (result ? "started successfully" : ("start failed: " + it->second->GetStatuses().original + ", will retry")); + bool result = cj_clientman->DoAutomaticDenominating(*node.connman, fee_estimator, mempool); + return "Mixing " + (result ? "started successfully" : ("start failed: " + cj_clientman->GetStatuses().original + ", will retry")); } if (request.params[0].get_str() == "stop") { - it->second->StopMixing(); + cj_clientman->StopMixing(); return "Mixing was stopped"; } if (request.params[0].get_str() == "reset") { - it->second->ResetPool(); + cj_clientman->ResetPool(); return "Mixing was reset"; } @@ -143,25 +146,26 @@ static UniValue getcoinjoininfo(const JSONRPCRequest& request) }.Check(request); UniValue obj(UniValue::VOBJ); + const NodeContext& node = EnsureAnyNodeContext(request.context); if (fMasternodeMode) { - coinJoinServer->GetJsonInfo(obj); + node.cj_ctx->server->GetJsonInfo(obj); return obj; } - #ifdef ENABLE_WALLET - CCoinJoinClientOptions::GetJsonInfo(obj); - obj.pushKV("queue_size", coinJoinClientQueueManager->GetQueueSize()); + obj.pushKV("queue_size", node.cj_ctx->queueman->GetQueueSize()); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) { return obj; } - coinJoinClientManagers.at(wallet->GetName())->GetJsonInfo(obj); + auto manager = ::coinJoinClientManagers->Get(*wallet); + CHECK_NONFATAL(manager != nullptr); + manager->GetJsonInfo(obj); obj.pushKV("keys_left", wallet->nKeysLeftSinceAutoBackup); obj.pushKV("warnings", wallet->nKeysLeftSinceAutoBackup < COINJOIN_KEYS_THRESHOLD_WARNING diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index e33f5412a8..0e3e619d2b 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -81,7 +81,8 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, *governance, false); + *m_node.chainman, *m_node.mempool, *governance, m_node.cj_ctx, + m_node.llmq_ctx, false); // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -153,7 +154,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, *governance, false); + *m_node.chainman, *m_node.mempool, *governance, m_node.cj_ctx, + m_node.llmq_ctx, false); const Consensus::Params& consensusParams = Params().GetConsensus(); constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS; @@ -227,7 +229,8 @@ BOOST_AUTO_TEST_CASE(DoS_banning) auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, *governance, false); + *m_node.chainman, *m_node.mempool, *governance, m_node.cj_ctx, + m_node.llmq_ctx, false); banman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -274,7 +277,8 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, *governance, false); + *m_node.chainman, *m_node.mempool, *governance, m_node.cj_ctx, + m_node.llmq_ctx, false); banman->ClearBanned(); gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number @@ -319,7 +323,8 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, *governance, false); + *m_node.chainman, *m_node.mempool, *governance, m_node.cj_ctx, + m_node.llmq_ctx, false); banman->ClearBanned(); int64_t nStartTime = GetTime(); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 4be86581b6..671ec1cbfb 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -58,6 +58,7 @@ #include #endif // ENABLE_WALLET #include +#include #include #include #include @@ -103,7 +104,7 @@ void DashTestSetup(NodeContext& node) { CChainState& chainstate = Assert(node.chainman)->ActiveChainstate(); - ::coinJoinServer = std::make_unique(chainstate, *node.connman, *node.mempool, *::masternodeSync); + node.cj_ctx = std::make_unique(chainstate, *node.connman, *node.mempool, *::masternodeSync, /* relay_txes */ true); ::deterministicMNManager = std::make_unique(chainstate, *node.connman, *node.evodb); node.llmq_ctx = std::make_unique(chainstate, *node.connman, *node.evodb, *sporkManager, *node.mempool, node.peerman, true, false); } @@ -114,7 +115,7 @@ void DashTestSetupClose(NodeContext& node) node.llmq_ctx->Stop(); node.llmq_ctx.reset(); ::deterministicMNManager.reset(); - ::coinJoinServer.reset(); + node.cj_ctx.reset(); } BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::vector& extra_args) @@ -205,9 +206,6 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve ::sporkManager = std::make_unique(); ::governance = std::make_unique(); ::masternodeSync = std::make_unique(*m_node.connman, *::governance); -#ifdef ENABLE_WALLET - ::coinJoinClientQueueManager = std::make_unique(*m_node.connman, *::masternodeSync); -#endif // ENABLE_WALLET m_node.creditPoolManager = std::make_unique(*m_node.evodb); @@ -224,9 +222,6 @@ ChainTestingSetup::~ChainTestingSetup() StopScriptCheckWorkerThreads(); GetMainSignals().FlushBackgroundCallbacks(); GetMainSignals().UnregisterBackgroundSignalScheduler(); -#ifdef ENABLE_WALLET - ::coinJoinClientQueueManager.reset(); -#endif // ENABLE_WALLET ::masternodeSync.reset(); ::governance.reset(); ::sporkManager.reset(); @@ -261,8 +256,8 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman, m_node.banman.get(), - *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, *governance, - false); + *m_node.scheduler, *m_node.chainman, *m_node.mempool, *governance, + m_node.cj_ctx, m_node.llmq_ctx, false); { CConnman::Options options; options.m_msgproc = m_node.peerman.get(); diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 4956d92c8a..b0bb48e8e7 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -46,7 +46,7 @@ public: // Dash Specific Wallet Init void AutoLockMasternodeCollaterals() const override; - void InitCoinJoinSettings() const override; + void InitCoinJoinSettings(const CJClientManager& clientman) const override; bool InitAutoBackup() const override; }; @@ -199,7 +199,7 @@ void WalletInit::AutoLockMasternodeCollaterals() const } } -void WalletInit::InitCoinJoinSettings() const +void WalletInit::InitCoinJoinSettings(const CJClientManager& clientman) const { CCoinJoinClientOptions::SetEnabled(!GetWallets().empty() ? gArgs.GetBoolArg("-enablecoinjoin", true) : false); if (!CCoinJoinClientOptions::IsEnabled()) { @@ -207,10 +207,12 @@ void WalletInit::InitCoinJoinSettings() const } bool fAutoStart = gArgs.GetBoolArg("-coinjoinautostart", DEFAULT_COINJOIN_AUTOSTART); for (auto& pwallet : GetWallets()) { + auto manager = clientman.Get(*pwallet); + assert(manager != nullptr); if (pwallet->IsLocked()) { - coinJoinClientManagers.at(pwallet->GetName())->StopMixing(); + manager->StopMixing(); } else if (fAutoStart) { - coinJoinClientManagers.at(pwallet->GetName())->StartMixing(); + manager->StartMixing(); } } LogPrintf("CoinJoin: autostart=%d, multisession=%d," /* Continued */ diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index 69be72a8ab..eac6a1776f 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -123,52 +123,54 @@ WalletTxOut MakeWalletTxOut(const CWallet& wallet, namespace CoinJoin = interfaces::CoinJoin; class CoinJoinImpl : public CoinJoin::Client { - std::shared_ptr m_manager; + CCoinJoinClientManager& m_manager; + public: - CoinJoinImpl(const std::shared_ptr& wallet) : m_manager(coinJoinClientManagers.at(wallet->GetName())) {} + CoinJoinImpl(const CJClientManager& clientman, const std::shared_ptr& wallet) + : m_manager(*Assert(clientman.Get(*wallet))) {} + void resetCachedBlocks() override { - m_manager->nCachedNumBlocks = std::numeric_limits::max(); + m_manager.nCachedNumBlocks = std::numeric_limits::max(); } void resetPool() override { - m_manager->ResetPool(); + m_manager.ResetPool(); } void disableAutobackups() override { - m_manager->fCreateAutoBackups = false; + m_manager.fCreateAutoBackups = false; } int getCachedBlocks() override { - return m_manager->nCachedNumBlocks; + return m_manager.nCachedNumBlocks; } std::string getSessionDenoms() override { - return m_manager->GetSessionDenoms(); + return m_manager.GetSessionDenoms(); } void setCachedBlocks(int nCachedBlocks) override { - m_manager->nCachedNumBlocks = nCachedBlocks; + m_manager.nCachedNumBlocks = nCachedBlocks; } bool isMixing() override { - return m_manager->IsMixing(); + return m_manager.IsMixing(); } bool startMixing() override { - return m_manager->StartMixing(); + return m_manager.StartMixing(); } void stopMixing() override { - m_manager->StopMixing(); + m_manager.StopMixing(); } }; class WalletImpl : public Wallet { public: - - explicit WalletImpl(const std::shared_ptr& wallet) : m_wallet(wallet), m_coinjoin(wallet) {} + explicit WalletImpl(const std::shared_ptr& wallet, const CJClientManager& clientman) : m_wallet(wallet), m_coinjoin(clientman, wallet) {} void markDirty() override { @@ -629,7 +631,7 @@ public: void setMockTime(int64_t time) override { return SetMockTime(time); } //! WalletLoader methods - std::unique_ptr createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector& warnings) override + std::unique_ptr createWallet(const CJClientManager& client_man, const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector& warnings) override { std::shared_ptr wallet; DatabaseOptions options; @@ -637,14 +639,14 @@ public: options.require_create = true; options.create_flags = wallet_creation_flags; options.create_passphrase = passphrase; - return MakeWallet(CreateWallet(*m_context.chain, name, true /* load_on_start */, options, status, error, warnings)); + return MakeWallet(CreateWallet(*m_context.chain, name, true /* load_on_start */, options, status, error, warnings), client_man); } - std::unique_ptr loadWallet(const std::string& name, bilingual_str& error, std::vector& warnings) override + std::unique_ptr loadWallet(const CJClientManager& client_man, const std::string& name, bilingual_str& error, std::vector& warnings) override { DatabaseOptions options; DatabaseStatus status; options.require_existing = true; - return MakeWallet(LoadWallet(*m_context.chain, name, true /* load_on_start */, options, status, error, warnings)); + return MakeWallet(LoadWallet(*m_context.chain, name, true /* load_on_start */, options, status, error, warnings), client_man); } std::string getWalletDir() override { @@ -662,7 +664,7 @@ public: { std::vector> wallets; for (const auto& wallet : GetWallets()) { - wallets.emplace_back(MakeWallet(wallet)); + wallets.emplace_back(MakeWallet(wallet, *::coinJoinClientManagers)); } return wallets; } @@ -680,7 +682,7 @@ public: } // namespace wallet namespace interfaces { -std::unique_ptr MakeWallet(const std::shared_ptr& wallet) { return wallet ? std::make_unique(wallet) : nullptr; } +std::unique_ptr MakeWallet(const std::shared_ptr& wallet, const CJClientManager& clientman) { return wallet ? std::make_unique(wallet, clientman) : nullptr; } std::unique_ptr MakeWalletLoader(Chain& chain, ArgsManager& args) { return std::make_unique(chain, args); } diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp index 5245f07964..1f35d2626c 100644 --- a/src/wallet/load.cpp +++ b/src/wallet/load.cpp @@ -141,9 +141,10 @@ void FlushWallets() for (const std::shared_ptr& pwallet : GetWallets()) { if (CCoinJoinClientOptions::IsEnabled()) { // Stop CoinJoin, release keys - auto it = coinJoinClientManagers.find(pwallet->GetName()); - it->second->ResetPool(); - it->second->StopMixing(); + auto cj_clientman = ::coinJoinClientManagers->Get(*pwallet); + assert(cj_clientman != nullptr); + cj_clientman->ResetPool(); + cj_clientman->StopMixing(); } pwallet->Flush(); } diff --git a/src/wallet/test/coinjoin_tests.cpp b/src/wallet/test/coinjoin_tests.cpp index 69c66000bd..81ff7aa702 100644 --- a/src/wallet/test/coinjoin_tests.cpp +++ b/src/wallet/test/coinjoin_tests.cpp @@ -207,8 +207,8 @@ public: BOOST_FIXTURE_TEST_CASE(coinjoin_manager_start_stop_tests, CTransactionBuilderTestSetup) { - BOOST_CHECK_EQUAL(coinJoinClientManagers.size(), 1); - auto& cj_man = coinJoinClientManagers.begin()->second; + BOOST_CHECK_EQUAL(::coinJoinClientManagers->raw().size(), 1); + auto& cj_man = ::coinJoinClientManagers->raw().begin()->second; BOOST_CHECK_EQUAL(cj_man->IsMixing(), false); BOOST_CHECK_EQUAL(cj_man->StartMixing(), true); BOOST_CHECK_EQUAL(cj_man->IsMixing(), true); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index de5230bc06..f9a1bd12b7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -119,9 +119,9 @@ bool AddWallet(const std::shared_ptr& wallet) } wallet->ConnectScriptPubKeyManNotifiers(); wallet->AutoLockMasternodeCollaterals(); - assert(::masternodeSync != nullptr); - coinJoinClientManagers.emplace(std::make_pair(wallet->GetName(), std::make_shared(*wallet, *::masternodeSync))); - g_wallet_init_interface.InitCoinJoinSettings(); + assert(::masternodeSync != nullptr && ::coinJoinClientManagers != nullptr); + ::coinJoinClientManagers->Add(*wallet); + g_wallet_init_interface.InitCoinJoinSettings(*::coinJoinClientManagers); return true; } @@ -140,9 +140,10 @@ bool RemoveWallet(const std::shared_ptr& wallet, std::optional lo if (i == vpwallets.end()) return false; vpwallets.erase(i); } - auto it = coinJoinClientManagers.find(wallet->GetName()); - coinJoinClientManagers.erase(it); - g_wallet_init_interface.InitCoinJoinSettings(); + + assert(::coinJoinClientManagers != nullptr); + ::coinJoinClientManagers->Remove(name); + g_wallet_init_interface.InitCoinJoinSettings(*::coinJoinClientManagers); // Write the wallet setting UpdateWalletSetting(chain, name, load_on_start, warnings); @@ -1639,10 +1640,9 @@ void CWallet::UnsetBlankWalletFlag(WalletBatch& batch) void CWallet::NewKeyPoolCallback() { - auto it = coinJoinClientManagers.find(GetName()); - if (it != coinJoinClientManagers.end()) { - it->second->StopMixing(); - } + assert(::coinJoinClientManagers != nullptr); + auto cj_clientman = ::coinJoinClientManagers->Get(*this); + if (cj_clientman != nullptr) cj_clientman->StopMixing(); nKeysLeftSinceAutoBackup = 0; } @@ -4805,13 +4805,13 @@ std::shared_ptr CWallet::Create(interfaces::Chain& chain, const std::st walletInstance->GetDatabase().IncrementUpdateCounter(); } - assert(::masternodeSync != nullptr); - coinJoinClientManagers.emplace(std::make_pair(walletInstance->GetName(), std::make_shared(*walletInstance, *::masternodeSync))); + assert(::masternodeSync != nullptr && ::coinJoinClientManagers != nullptr); + ::coinJoinClientManagers->Add(*walletInstance); { LOCK(cs_wallets); for (auto& load_wallet : g_load_wallet_fns) { - load_wallet(interfaces::MakeWallet(walletInstance)); + load_wallet(interfaces::MakeWallet(walletInstance, *::coinJoinClientManagers)); } } diff --git a/src/walletinitinterface.h b/src/walletinitinterface.h index 1fb20e59c0..84d79bf60a 100644 --- a/src/walletinitinterface.h +++ b/src/walletinitinterface.h @@ -6,6 +6,7 @@ #define BITCOIN_WALLETINITINTERFACE_H class ArgsManager; +class CJClientManager; struct NodeContext; @@ -22,7 +23,7 @@ public: // Dash Specific WalletInitInterface virtual void AutoLockMasternodeCollaterals() const = 0; - virtual void InitCoinJoinSettings() const = 0; + virtual void InitCoinJoinSettings(const CJClientManager& clientman) const = 0; virtual bool InitAutoBackup() const = 0; virtual ~WalletInitInterface() {} diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index e7911fa97a..9013121a55 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -65,6 +65,8 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "logging -> util/system -> stacktraces -> logging" "logging -> util/system -> util/getuniquepath -> random -> logging" "coinjoin/client -> coinjoin/util -> wallet/wallet -> coinjoin/client" + "coinjoin/client -> net_processing -> coinjoin/context -> coinjoin/client" + "coinjoin/context -> coinjoin/server -> net_processing -> coinjoin/context" "qt/appearancewidget -> qt/guiutil -> qt/optionsdialog -> qt/appearancewidget" "qt/guiutil -> qt/optionsdialog -> qt/optionsmodel -> qt/guiutil"