diff --git a/src/Makefile.am b/src/Makefile.am index 559382876ebf..9145ad2380c5 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 68176f76d9a3..5fd6f691723a 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 e336475bc22b..65ebbb88c57d 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 @@ class CPendingDsaRequest } }; +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 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession 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 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession 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 @@ class CCoinJoinClientQueueManager : public CCoinJoinBaseManager 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 @@ class CCoinJoinClientManager 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 @@ class CCoinJoinClientManager 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 @@ class CCoinJoinClientManager 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 000000000000..4e8c7253208c --- /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 000000000000..d05da33e3c7c --- /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 382e95d7eb54..5eae338f697e 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 c2e54aef61ae..de509019bec1 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 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager 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 5e1d16635bb2..f32ee68c6657 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 b01bbdac9f16..f3c0d8e1d20d 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 @@ class CDSNotificationInterface : public CValidationInterface 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 4806650d5e6d..ae088b36c4a4 100644 --- a/src/dummywallet.cpp +++ b/src/dummywallet.cpp @@ -24,7 +24,7 @@ class DummyWalletInit : public WalletInitInterface { // 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 ce51b7426282..c5cfa05960c3 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 7232bc79f6bd..734c8e0e995c 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 a31d82d11cdc..03fba7cec671 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 3437175d627c..9ff6b0ed3ad9 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 2f2649ba708d..46f4bb30e93d 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 @@ class PeerManagerImpl final : public PeerManager 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 c29acec7cd45..ed4865a69723 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 ed3d4b9ac8b3..7772fcf8a3df 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 f44cc8d51b54..91ff6df05d6d 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 f646419a6c97..b5958ba75f95 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 387479831e4c..23c58c9eede2 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 ddd2fd346a7f..0afbf282e0af 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 f3e6d2993aa3..2dd16529eb52 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 e33f5412a819..0e3e619d2bcc 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 4be86581b6a5..671ec1cbfbab 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 4956d92c8a56..b0bb48e8e7bf 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -46,7 +46,7 @@ class WalletInit : public WalletInitInterface // 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 69be72a8ab4f..eac6a1776fa9 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 @@ class WalletLoaderImpl : public WalletLoader 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 @@ class WalletLoaderImpl : public WalletLoader 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 @@ class WalletLoaderImpl : public WalletLoader { 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 @@ class WalletLoaderImpl : public WalletLoader } // 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 5245f0796439..1f35d2626c99 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 69c66000bda5..81ff7aa702f4 100644 --- a/src/wallet/test/coinjoin_tests.cpp +++ b/src/wallet/test/coinjoin_tests.cpp @@ -207,8 +207,8 @@ class CTransactionBuilderTestSetup : public TestChain100Setup 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 de5230bc068a..f9a1bd12b727 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 1fb20e59c017..84d79bf60a08 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 @@ class WalletInitInterface { // 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 e7911fa97a01..9013121a559d 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"