refactor: subsume CoinJoin objects under CJContext, deglobalize coinJoin{ClientQueueManager,Server} (#5337)

## Motivation

CoinJoin's subsystems are initialized by variables and managers that
occupy the global context. The _extent_ to which these subsystems
entrench themselves into the codebase is difficult to assess and moving
them out of the global context forces us to enumerate the subsystems in
the codebase that rely on CoinJoin logic and enumerate the order in
which components are initialized and destroyed.

Keeping this in mind, the scope of this pull request aims to:

* Reduce the amount of CoinJoin-specific entities present in the global
scope
* Make the remaining usage of these entities in the global scope
explicit and easily searchable

## Additional Information

* The initialization of `CCoinJoinClientQueueManager` is dependent on
blocks-only mode being disabled (which can be alternatively interpreted
as enabling the relay of transactions). The same applies to
`CBlockPolicyEstimator`, which `CCoinJoinClientQueueManager` depends.

Therefore, `CCoinJoinClientQueueManager` is only initialized if
transaction relaying is enabled and so is its scheduled maintenance
task. This can be found by looking at `init.cpp`
[here](93f8df1c31/src/init.cpp (L1681-L1683)),
[here](93f8df1c31/src/init.cpp (L2253-L2255))
and
[here](93f8df1c31/src/init.cpp (L2326-L2327)).
  
For this reason, `CBlockPolicyEstimator` is not a member of `CJContext`
and its usage is fulfilled by passing it as a reference when
initializing the scheduling task.

* `CJClientManager` has not used `CConnman` or `CTxMemPool` as `const`
as existing code that is outside the scope of this PR would cast away
constness, which would be unacceptable. Furthermore, some logical paths
are taken that will grind to a halt if they are stored as `const`.

  Examples of such a call chains would be:

* `CJClientManager::DoMaintenance >
CCoinJoinClientManager::DoMaintenance > DoAutomaticDenominating >
CCoinJoinClientSession::DoAutomaticDenominating >
CCoinJoinClientSession::StartNewQueue > CConnman::AddPendingMasternode`
which modifies `CConnman::vPendingMasternodes`, which is non-const
behaviour

* `CJClientManager::DoMaintenance >
CCoinJoinClientManager::DoMaintenance > DoAutomaticDenominating >
CCoinJoin::IsCollateralValid > AcceptToMemoryPool` which adds a
transaction to the memory pool, which is non-const behaviour

* There were cppcheck [linter
failures](https://github.com/dashpay/dash/pull/5337#issuecomment-1685084688)
that seemed to be caused by the usage of `Assert` in
`coinjoin/client.h`. This seems to be resolved by backporting
[bitcoin#24714](https://github.com/bitcoin/bitcoin/pull/24714). (Thanks
@knst!)
    * Depends on #5546

---------

Co-authored-by: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com>
Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com>
This commit is contained in:
Kittywhiskers Van Gogh 2023-09-13 23:22:38 +05:30 committed by GitHub
parent 38e70430b9
commit 41a6613fba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 477 additions and 332 deletions

View File

@ -149,6 +149,7 @@ BITCOIN_CORE_H = \
clientversion.h \ clientversion.h \
coinjoin/coinjoin.h \ coinjoin/coinjoin.h \
coinjoin/client.h \ coinjoin/client.h \
coinjoin/context.h \
coinjoin/options.h \ coinjoin/options.h \
coinjoin/server.h \ coinjoin/server.h \
coinjoin/util.h \ coinjoin/util.h \
@ -391,6 +392,7 @@ libbitcoin_server_a_SOURCES = \
blockfilter.cpp \ blockfilter.cpp \
chain.cpp \ chain.cpp \
coinjoin/coinjoin.cpp \ coinjoin/coinjoin.cpp \
coinjoin/context.cpp \
coinjoin/options.cpp \ coinjoin/options.cpp \
coinjoin/server.cpp \ coinjoin/server.cpp \
consensus/tx_verify.cpp \ consensus/tx_verify.cpp \

File diff suppressed because it is too large Load Diff

View File

@ -7,33 +7,31 @@
#include <coinjoin/util.h> #include <coinjoin/util.h>
#include <coinjoin/coinjoin.h> #include <coinjoin/coinjoin.h>
#include <util/check.h>
#include <util/translation.h> #include <util/translation.h>
#include <atomic> #include <atomic>
#include <deque> #include <deque>
#include <memory>
#include <utility> #include <utility>
class CDeterministicMN; class CBlockPolicyEstimator;
using CDeterministicMNCPtr = std::shared_ptr<const CDeterministicMN>;
class CCoinJoinClientManager; class CCoinJoinClientManager;
class CCoinJoinClientQueueManager; class CCoinJoinClientQueueManager;
class CBlockPolicyEstimator;
class CConnman; class CConnman;
class CDeterministicMN;
class CJClientManager;
class CNode; class CNode;
class CMasternodeSync;
class CTxMemPool; class CTxMemPool;
class PeerManager; class PeerManager;
class UniValue; class UniValue;
class CMasternodeSync;
using CDeterministicMNCPtr = std::shared_ptr<const CDeterministicMN>;
// The main object for accessing mixing // The main object for accessing mixing
extern std::map<const std::string, std::shared_ptr<CCoinJoinClientManager>> coinJoinClientManagers; extern std::unique_ptr<CJClientManager> coinJoinClientManagers;
// The object to track mixing queues
extern std::unique_ptr<CCoinJoinClientQueueManager> coinJoinClientQueueManager;
class CPendingDsaRequest class CPendingDsaRequest
{ {
@ -72,10 +70,53 @@ public:
} }
}; };
class CJClientManager {
public:
using wallet_name_cjman_map = std::map<const std::string, std::unique_ptr<CCoinJoinClientManager>>;
public:
CJClientManager(CConnman& connman, CTxMemPool& mempool, const CMasternodeSync& mn_sync,
const std::unique_ptr<CCoinJoinClientQueueManager>& 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<CCoinJoinClientQueueManager>& m_queueman;
wallet_name_cjman_map m_wallet_manager_map;
};
class CCoinJoinClientSession : public CCoinJoinBaseSession class CCoinJoinClientSession : public CCoinJoinBaseSession
{ {
private: private:
CWallet& m_wallet;
CJClientManager& m_clientman;
CCoinJoinClientManager& m_manager;
const CMasternodeSync& m_mn_sync; const CMasternodeSync& m_mn_sync;
const std::unique_ptr<CCoinJoinClientQueueManager>& m_queueman;
std::vector<COutPoint> vecOutPointLocked; std::vector<COutPoint> vecOutPointLocked;
@ -88,8 +129,6 @@ private:
CKeyHolderStorage keyHolderStorage; // storage for keys used in PrepareDenominate CKeyHolderStorage keyHolderStorage; // storage for keys used in PrepareDenominate
CWallet& mixingWallet;
/// Create denominations /// Create denominations
bool CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate); bool CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate);
bool CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals); bool CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals);
@ -125,10 +164,9 @@ private:
void SetNull() EXCLUSIVE_LOCKS_REQUIRED(cs_coinjoin); void SetNull() EXCLUSIVE_LOCKS_REQUIRED(cs_coinjoin);
public: public:
explicit CCoinJoinClientSession(CWallet& pwallet, const CMasternodeSync& mn_sync) : explicit CCoinJoinClientSession(CWallet& pwallet, CJClientManager& clientman, const CMasternodeSync& mn_sync,
m_mn_sync(mn_sync), mixingWallet(pwallet) const std::unique_ptr<CCoinJoinClientQueueManager>& 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); 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: private:
CConnman& connman; CConnman& connman;
CJClientManager& m_clientman;
const CMasternodeSync& m_mn_sync; const CMasternodeSync& m_mn_sync;
mutable Mutex cs_ProcessDSQueue; mutable Mutex cs_ProcessDSQueue;
public: public:
explicit CCoinJoinClientQueueManager(CConnman& _connman, const CMasternodeSync& mn_sync) : explicit CCoinJoinClientQueueManager(CConnman& _connman, CJClientManager& clientman, const CMasternodeSync& mn_sync) :
connman(_connman), m_mn_sync(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 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); void ProcessDSQueue(const CNode& peer, PeerManager& peerman, CDataStream& vRecv);
@ -176,10 +215,14 @@ public:
class CCoinJoinClientManager class CCoinJoinClientManager
{ {
private: private:
// Keep track of the used Masternodes CWallet& m_wallet;
std::vector<COutPoint> vecMasternodesUsed; CJClientManager& m_clientman;
const CMasternodeSync& m_mn_sync; const CMasternodeSync& m_mn_sync;
const std::unique_ptr<CCoinJoinClientQueueManager>& m_queueman;
// Keep track of the used Masternodes
std::vector<COutPoint> vecMasternodesUsed;
mutable Mutex cs_deqsessions; mutable Mutex cs_deqsessions;
// TODO: or map<denom, CCoinJoinClientSession> ?? // TODO: or map<denom, CCoinJoinClientSession> ??
@ -191,8 +234,6 @@ private:
int nMinBlocksToWait{1}; // how many blocks to wait for after one successful mixing tx in non-multisession mode int nMinBlocksToWait{1}; // how many blocks to wait for after one successful mixing tx in non-multisession mode
bilingual_str strAutoDenomResult; bilingual_str strAutoDenomResult;
CWallet& mixingWallet;
// Keep track of current block height // Keep track of current block height
int nCachedBlockHeight{0}; int nCachedBlockHeight{0};
@ -209,8 +250,9 @@ public:
CCoinJoinClientManager(CCoinJoinClientManager const&) = delete; CCoinJoinClientManager(CCoinJoinClientManager const&) = delete;
CCoinJoinClientManager& operator=(CCoinJoinClientManager const&) = delete; CCoinJoinClientManager& operator=(CCoinJoinClientManager const&) = delete;
explicit CCoinJoinClientManager(CWallet& wallet, const CMasternodeSync& mn_sync) : explicit CCoinJoinClientManager(CWallet& wallet, CJClientManager& clientman, const CMasternodeSync& mn_sync,
m_mn_sync(mn_sync), mixingWallet(wallet) {} const std::unique_ptr<CCoinJoinClientQueueManager>& 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); void ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_deqsessions);
@ -246,7 +288,4 @@ public:
void GetJsonInfo(UniValue& obj) const LOCKS_EXCLUDED(cs_deqsessions); void GetJsonInfo(UniValue& obj) const LOCKS_EXCLUDED(cs_deqsessions);
}; };
void DoCoinJoinMaintenance(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool);
#endif // BITCOIN_COINJOIN_CLIENT_H #endif // BITCOIN_COINJOIN_CLIENT_H

34
src/coinjoin/context.cpp Normal file
View File

@ -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 <coinjoin/context.h>
#include <net.h>
#include <policy/fees.h>
#include <txmempool.h>
#ifdef ENABLE_WALLET
#include <coinjoin/client.h>
#endif // ENABLE_WALLET
#include <coinjoin/server.h>
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<CJClientManager>(connman, mempool, mn_sync, queueman);
return ::coinJoinClientManagers.get();
}()
},
queueman {relay_txes ? std::make_unique<CCoinJoinClientQueueManager>(connman, *clientman, mn_sync) : nullptr},
#endif // ENABLE_WALLET
server{std::make_unique<CCoinJoinServer>(chainstate, connman, mempool, mn_sync)}
{}
CJContext::~CJContext() {
#ifdef ENABLE_WALLET
::coinJoinClientManagers.reset();
#endif // ENABLE_WALLET
}

39
src/coinjoin/context.h Normal file
View File

@ -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 <config/bitcoin-config.h>
#endif
#include <memory>
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<CCoinJoinClientQueueManager> queueman;
#endif // ENABLE_WALLET
const std::unique_ptr<CCoinJoinServer> server;
};
#endif // BITCOIN_COINJOIN_CONTEXT_H

View File

@ -23,7 +23,6 @@
#include <univalue.h> #include <univalue.h>
std::unique_ptr<CCoinJoinServer> coinJoinServer;
constexpr static CAmount DEFAULT_MAX_RAW_TX_FEE{COIN / 10}; constexpr static CAmount DEFAULT_MAX_RAW_TX_FEE{COIN / 10};
void CCoinJoinServer::ProcessMessage(CNode& peer, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv) 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; nState = nStateNew;
} }
void CCoinJoinServer::DoMaintenance() const void CCoinJoinServer::DoMaintenance()
{ {
if (!fMasternodeMode) return; // only run on masternodes if (!fMasternodeMode) return; // only run on masternodes
if (!m_mn_sync.IsBlockchainSynced()) return; if (!m_mn_sync.IsBlockchainSynced()) return;
if (ShutdownRequested()) return; if (ShutdownRequested()) return;
if (!coinJoinServer) return; CheckForCompleteQueue();
CheckPool();
coinJoinServer->CheckForCompleteQueue(); CheckTimeout();
coinJoinServer->CheckPool();
coinJoinServer->CheckTimeout();
} }
void CCoinJoinServer::GetJsonInfo(UniValue& obj) const void CCoinJoinServer::GetJsonInfo(UniValue& obj) const

View File

@ -15,9 +15,6 @@ class PeerManager;
class UniValue; class UniValue;
// The main object for accessing mixing
extern std::unique_ptr<CCoinJoinServer> coinJoinServer;
/** Used to keep track of current status of mixing pool /** Used to keep track of current status of mixing pool
*/ */
class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager
@ -96,7 +93,7 @@ public:
void CheckTimeout(); void CheckTimeout();
void CheckForCompleteQueue(); void CheckForCompleteQueue();
void DoMaintenance() const; void DoMaintenance();
void GetJsonInfo(UniValue& obj) const; void GetJsonInfo(UniValue& obj) const;
}; };

View File

@ -7,6 +7,7 @@
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include <coinjoin/client.h> #include <coinjoin/client.h>
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
#include <coinjoin/context.h>
#include <dsnotificationinterface.h> #include <dsnotificationinterface.h>
#include <governance/governance.h> #include <governance/governance.h>
#include <masternode/sync.h> #include <masternode/sync.h>
@ -23,8 +24,9 @@
CDSNotificationInterface::CDSNotificationInterface(CConnman& _connman, CDSNotificationInterface::CDSNotificationInterface(CConnman& _connman,
CMasternodeSync& _mn_sync, const std::unique_ptr<CDeterministicMNManager>& _dmnman, CMasternodeSync& _mn_sync, const std::unique_ptr<CDeterministicMNManager>& _dmnman,
CGovernanceManager& _govman, const std::unique_ptr<LLMQContext>& _llmq_ctx CGovernanceManager& _govman, const std::unique_ptr<LLMQContext>& _llmq_ctx,
) : connman(_connman), m_mn_sync(_mn_sync), dmnman(_dmnman), govman(_govman), llmq_ctx(_llmq_ctx) {} const std::unique_ptr<CJContext>& _cj_ctx
) : connman(_connman), m_mn_sync(_mn_sync), dmnman(_dmnman), govman(_govman), llmq_ctx(_llmq_ctx), cj_ctx(_cj_ctx) {}
void CDSNotificationInterface::InitializeCurrentBlockTip() void CDSNotificationInterface::InitializeCurrentBlockTip()
{ {
@ -66,7 +68,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
CCoinJoin::UpdatedBlockTip(pindexNew, *llmq_ctx->clhandler, m_mn_sync); CCoinJoin::UpdatedBlockTip(pindexNew, *llmq_ctx->clhandler, m_mn_sync);
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
for (auto& pair : coinJoinClientManagers) { for (auto& pair : cj_ctx->clientman->raw()) {
pair.second->UpdatedBlockTip(pindexNew); pair.second->UpdatedBlockTip(pindexNew);
} }
#endif // ENABLE_WALLET #endif // ENABLE_WALLET

View File

@ -11,6 +11,7 @@ class CConnman;
class CDeterministicMNManager; class CDeterministicMNManager;
class CGovernanceManager; class CGovernanceManager;
class CMasternodeSync; class CMasternodeSync;
struct CJContext;
struct LLMQContext; struct LLMQContext;
class CDSNotificationInterface : public CValidationInterface class CDSNotificationInterface : public CValidationInterface
@ -18,7 +19,8 @@ class CDSNotificationInterface : public CValidationInterface
public: public:
explicit CDSNotificationInterface(CConnman& _connman, explicit CDSNotificationInterface(CConnman& _connman,
CMasternodeSync& _mn_sync, const std::unique_ptr<CDeterministicMNManager>& _dmnman, CMasternodeSync& _mn_sync, const std::unique_ptr<CDeterministicMNManager>& _dmnman,
CGovernanceManager& _govman, const std::unique_ptr<LLMQContext>& _llmq_ctx); CGovernanceManager& _govman, const std::unique_ptr<LLMQContext>& _llmq_ctx,
const std::unique_ptr<CJContext>& _cj_ctx);
virtual ~CDSNotificationInterface() = default; virtual ~CDSNotificationInterface() = default;
// a small helper to initialize current block height in sub-modules on startup // a small helper to initialize current block height in sub-modules on startup
@ -45,6 +47,7 @@ private:
CGovernanceManager& govman; CGovernanceManager& govman;
const std::unique_ptr<LLMQContext>& llmq_ctx; const std::unique_ptr<LLMQContext>& llmq_ctx;
const std::unique_ptr<CJContext>& cj_ctx;
}; };
#endif // BITCOIN_DSNOTIFICATIONINTERFACE_H #endif // BITCOIN_DSNOTIFICATIONINTERFACE_H

View File

@ -24,7 +24,7 @@ public:
// Dash Specific WalletInitInterface InitCoinJoinSettings // Dash Specific WalletInitInterface InitCoinJoinSettings
void AutoLockMasternodeCollaterals() const override {} void AutoLockMasternodeCollaterals() const override {}
void InitCoinJoinSettings() const override {} void InitCoinJoinSettings(const CJClientManager& clientman) const override {}
bool InitAutoBackup() const override {return true;} bool InitAutoBackup() const override {return true;}
}; };
@ -74,7 +74,7 @@ const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
namespace interfaces { namespace interfaces {
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet, const CJClientManager& clientman)
{ {
throw std::logic_error("Wallet function called in non-wallet build."); throw std::logic_error("Wallet function called in non-wallet build.");
} }

View File

@ -68,6 +68,7 @@
#include <validationinterface.h> #include <validationinterface.h>
#include <masternode/node.h> #include <masternode/node.h>
#include <coinjoin/context.h>
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include <coinjoin/client.h> #include <coinjoin/client.h>
#include <coinjoin/options.h> #include <coinjoin/options.h>
@ -320,10 +321,6 @@ void PrepareShutdown(NodeContext& node)
// After all scheduled tasks have been flushed, destroy pointers // After all scheduled tasks have been flushed, destroy pointers
// and reset all to nullptr. // and reset all to nullptr.
::coinJoinServer.reset();
#ifdef ENABLE_WALLET
::coinJoinClientQueueManager.reset();
#endif // ENABLE_WALLET
::governance.reset(); ::governance.reset();
::sporkManager.reset(); ::sporkManager.reset();
::masternodeSync.reset(); ::masternodeSync.reset();
@ -393,6 +390,11 @@ void PrepareShutdown(NodeContext& node)
} }
node.chain_clients.clear(); node.chain_clients.clear();
// After all wallets are removed, destroy all CoinJoin objects
// and reset them to nullptr
node.cj_ctx.reset();
UnregisterAllValidationInterfaces(); UnregisterAllValidationInterfaces();
GetMainSignals().UnregisterBackgroundSignalScheduler(); GetMainSignals().UnregisterBackgroundSignalScheduler();
} }
@ -1698,7 +1700,8 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
assert(!node.peerman); assert(!node.peerman);
node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(), 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()); RegisterValidationInterface(node.peerman.get());
assert(!::sporkManager); assert(!::sporkManager);
@ -1852,7 +1855,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
assert(masternodeSync != nullptr); assert(masternodeSync != nullptr);
assert(governance != nullptr); assert(governance != nullptr);
pdsNotificationInterface = new CDSNotificationInterface( pdsNotificationInterface = new CDSNotificationInterface(
*node.connman, *::masternodeSync, ::deterministicMNManager, *::governance, node.llmq_ctx *node.connman, *::masternodeSync, ::deterministicMNManager, *::governance, node.llmq_ctx, node.cj_ctx
); );
RegisterValidationInterface(pdsNotificationInterface); RegisterValidationInterface(pdsNotificationInterface);
@ -2191,6 +2194,14 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
return false; return false;
} }
// ********************************************************* Step 7c: Setup CoinJoin
node.cj_ctx = std::make_unique<CJContext>(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 // ********************************************************* Step 8: start indexers
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex); g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex);
@ -2252,18 +2263,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
return false; return false;
} }
// ********************************************************* Step 10a: Setup CoinJoin // ********************************************************* Step 10a: Load cache data
::coinJoinServer = std::make_unique<CCoinJoinServer>(chainman.ActiveChainstate(), *node.connman, *node.mempool, *::masternodeSync);
#ifdef ENABLE_WALLET
if (!ignores_incoming_txs) {
::coinJoinClientQueueManager = std::make_unique<CCoinJoinClientQueueManager>(*node.connman, *::masternodeSync);
}
#endif // ENABLE_WALLET
g_wallet_init_interface.InitCoinJoinSettings();
// ********************************************************* Step 10b: Load cache data
// LOAD SERIALIZED DAT FILES INTO DATA CACHES FOR INTERNAL USE // 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(&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(&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}); node.scheduler->scheduleEvery(std::bind(&CDeterministicMNManager::DoMaintenance, std::ref(*deterministicMNManager)), std::chrono::seconds{10});
if (!fDisableGovernance) { if (!fDisableGovernance) {
@ -2326,11 +2326,12 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
} }
if (fMasternodeMode) { 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}); node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.llmq_ctx->qdkgsman)), std::chrono::hours{1});
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
} else if (!ignores_incoming_txs) { } 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 #endif // ENABLE_WALLET
} }

View File

@ -26,6 +26,7 @@
class CCoinControl; class CCoinControl;
class CFeeRate; class CFeeRate;
class CJClientManager;
class CKey; class CKey;
class CWallet; class CWallet;
enum class FeeReason; enum class FeeReason;
@ -353,10 +354,10 @@ class WalletLoader : public ChainClient
{ {
public: public:
//! Create new wallet. //! Create new wallet.
virtual std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0; virtual std::unique_ptr<Wallet> createWallet(const CJClientManager& client_man, const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
//! Load existing wallet. //! Load existing wallet.
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0; virtual std::unique_ptr<Wallet> loadWallet(const CJClientManager& client_man, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
//! Return default wallet directory. //! Return default wallet directory.
virtual std::string getWalletDir() = 0; virtual std::string getWalletDir() = 0;
@ -454,7 +455,7 @@ struct WalletTxOut
//! Return implementation of Wallet interface. This function is defined in //! Return implementation of Wallet interface. This function is defined in
//! dummywallet.cpp and throws if the wallet component is not compiled. //! dummywallet.cpp and throws if the wallet component is not compiled.
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet); std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet, const CJClientManager& clientman);
//! Return implementation of ChainClient interface for a wallet loader. This //! Return implementation of ChainClient interface for a wallet loader. This
//! function will be undefined in builds where ENABLE_WALLET is false. //! function will be undefined in builds where ENABLE_WALLET is false.

View File

@ -13,16 +13,16 @@
#include <shutdown.h> #include <shutdown.h>
#include <validation.h> #include <validation.h>
#include <util/ranges.h> #include <util/ranges.h>
#include <coinjoin/context.h>
void CMasternodeUtils::DoMaintenance(CConnman& connman, const CMasternodeSync& mn_sync, const CJContext& cj_ctx)
void CMasternodeUtils::DoMaintenance(CConnman& connman, const CMasternodeSync& mn_sync)
{ {
if (!mn_sync.IsBlockchainSynced()) return; if (!mn_sync.IsBlockchainSynced()) return;
if (ShutdownRequested()) return; if (ShutdownRequested()) return;
std::vector<CDeterministicMNCPtr> vecDmns; // will be empty when no wallet std::vector<CDeterministicMNCPtr> vecDmns; // will be empty when no wallet
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
for (const auto& pair : coinJoinClientManagers) { for (auto& pair : cj_ctx.clientman->raw()) {
pair.second->GetMixingMasternodesInfo(vecDmns); pair.second->GetMixingMasternodesInfo(vecDmns);
} }
#endif // ENABLE_WALLET #endif // ENABLE_WALLET

View File

@ -7,11 +7,12 @@
class CConnman; class CConnman;
class CMasternodeSync; class CMasternodeSync;
struct CJContext;
class CMasternodeUtils class CMasternodeUtils
{ {
public: 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 #endif // BITCOIN_MASTERNODE_UTILS_H

View File

@ -44,6 +44,7 @@
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include <coinjoin/client.h> #include <coinjoin/client.h>
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
#include <coinjoin/context.h>
#include <coinjoin/server.h> #include <coinjoin/server.h>
#include <evo/deterministicmns.h> #include <evo/deterministicmns.h>
@ -220,7 +221,8 @@ class PeerManagerImpl final : public PeerManager
public: public:
PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman,
CTxMemPool& pool, const std::unique_ptr<LLMQContext>& llmq_ctx, CGovernanceManager& govman, bool ignore_incoming_txs); CTxMemPool& pool, CGovernanceManager& govman, const std::unique_ptr<CJContext>& cj_ctx,
const std::unique_ptr<LLMQContext>& llmq_ctx, bool ignore_incoming_txs);
/** Overridden from CValidationInterface. */ /** Overridden from CValidationInterface. */
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override; void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override;
@ -309,6 +311,7 @@ private:
BanMan* const m_banman; BanMan* const m_banman;
ChainstateManager& m_chainman; ChainstateManager& m_chainman;
CTxMemPool& m_mempool; CTxMemPool& m_mempool;
const std::unique_ptr<CJContext>& m_cj_ctx;
const std::unique_ptr<LLMQContext>& m_llmq_ctx; const std::unique_ptr<LLMQContext>& m_llmq_ctx;
CGovernanceManager& m_govman; CGovernanceManager& m_govman;
@ -1543,20 +1546,23 @@ bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex, const Conse
std::unique_ptr<PeerManager> PeerManager::make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, std::unique_ptr<PeerManager> PeerManager::make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman,
CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool,
const std::unique_ptr<LLMQContext>& llmq_ctx, CGovernanceManager& govman, bool ignore_incoming_txs) CGovernanceManager& govman, const std::unique_ptr<CJContext>& cj_ctx,
const std::unique_ptr<LLMQContext>& llmq_ctx, bool ignore_incoming_txs)
{ {
return std::make_unique<PeerManagerImpl>(chainparams, connman, addrman, banman, scheduler, chainman, pool, llmq_ctx, govman, ignore_incoming_txs); return std::make_unique<PeerManagerImpl>(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, PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman,
CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool,
const std::unique_ptr<LLMQContext>& llmq_ctx, CGovernanceManager& govman, bool ignore_incoming_txs) CGovernanceManager& govman, const std::unique_ptr<CJContext>& cj_ctx,
const std::unique_ptr<LLMQContext>& llmq_ctx, bool ignore_incoming_txs)
: m_chainparams(chainparams), : m_chainparams(chainparams),
m_connman(connman), m_connman(connman),
m_addrman(addrman), m_addrman(addrman),
m_banman(banman), m_banman(banman),
m_chainman(chainman), m_chainman(chainman),
m_mempool(pool), m_mempool(pool),
m_cj_ctx(cj_ctx),
m_llmq_ctx(llmq_ctx), m_llmq_ctx(llmq_ctx),
m_govman(govman), m_govman(govman),
m_stale_tip_check_time(0), m_stale_tip_check_time(0),
@ -4313,12 +4319,12 @@ void PeerManagerImpl::ProcessMessage(
{ {
//probably one the extensions //probably one the extensions
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
coinJoinClientQueueManager->ProcessMessage(pfrom, *this, msg_type, vRecv); m_cj_ctx->queueman->ProcessMessage(pfrom, *this, msg_type, vRecv);
for (auto& pair : coinJoinClientManagers) { for (auto& pair : m_cj_ctx->clientman->raw()) {
pair.second->ProcessMessage(pfrom, *this, m_connman, m_mempool, msg_type, vRecv); pair.second->ProcessMessage(pfrom, *this, m_connman, m_mempool, msg_type, vRecv);
} }
#endif // ENABLE_WALLET #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); sporkManager->ProcessMessage(pfrom, *this, m_connman, msg_type, vRecv);
::masternodeSync->ProcessMessage(pfrom, msg_type, vRecv); ::masternodeSync->ProcessMessage(pfrom, msg_type, vRecv);
m_govman.ProcessMessage(pfrom, *this, m_connman, msg_type, vRecv); m_govman.ProcessMessage(pfrom, *this, m_connman, msg_type, vRecv);

View File

@ -15,6 +15,8 @@
class CAddrMan; class CAddrMan;
class CTxMemPool; class CTxMemPool;
class ChainstateManager; class ChainstateManager;
class CCoinJoinServer;
struct CJContext;
struct LLMQContext; struct LLMQContext;
class CGovernanceManager; class CGovernanceManager;
@ -40,7 +42,8 @@ class PeerManager : public CValidationInterface, public NetEventsInterface
public: public:
static std::unique_ptr<PeerManager> make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, static std::unique_ptr<PeerManager> make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman,
CTxMemPool& pool, const std::unique_ptr<LLMQContext>& llmq_ctx, CGovernanceManager& govman, bool ignore_incoming_txs); CTxMemPool& pool, CGovernanceManager& govman, const std::unique_ptr<CJContext>& cj_ctx,
const std::unique_ptr<LLMQContext>& llmq_ctx, bool ignore_incoming_txs);
virtual ~PeerManager() { } virtual ~PeerManager() { }
/** Get statistics from node state */ /** Get statistics from node state */

View File

@ -6,6 +6,7 @@
#include <addrman.h> #include <addrman.h>
#include <banman.h> #include <banman.h>
#include <coinjoin/context.h>
#include <evo/creditpool.h> #include <evo/creditpool.h>
#include <interfaces/chain.h> #include <interfaces/chain.h>
#include <llmq/context.h> #include <llmq/context.h>

View File

@ -16,12 +16,14 @@ class CAddrMan;
class CBlockPolicyEstimator; class CBlockPolicyEstimator;
class CConnman; class CConnman;
class CCreditPoolManager; class CCreditPoolManager;
class ChainstateManager;
class CEvoDB;
class CScheduler; class CScheduler;
class CTxMemPool; class CTxMemPool;
class ChainstateManager;
struct LLMQContext;
class PeerManager; class PeerManager;
class CEvoDB; struct CJContext;
struct LLMQContext;
namespace interfaces { namespace interfaces {
class Chain; class Chain;
class ChainClient; class ChainClient;
@ -58,6 +60,7 @@ struct NodeContext {
//! Dash //! Dash
std::unique_ptr<LLMQContext> llmq_ctx; std::unique_ptr<LLMQContext> llmq_ctx;
std::unique_ptr<CCreditPoolManager> creditPoolManager; std::unique_ptr<CCreditPoolManager> creditPoolManager;
std::unique_ptr<CJContext> cj_ctx;
std::unique_ptr<CEvoDB> evodb; std::unique_ptr<CEvoDB> evodb;

View File

@ -14,6 +14,7 @@
#include <qt/qvalidatedlineedit.h> #include <qt/qvalidatedlineedit.h>
#include <qt/walletmodel.h> #include <qt/walletmodel.h>
#include <coinjoin/client.h>
#include <key.h> #include <key.h>
#include <key_io.h> #include <key_io.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
@ -108,7 +109,8 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
OptionsModel optionsModel(node); OptionsModel optionsModel(node);
ClientModel clientModel(node, &optionsModel); ClientModel clientModel(node, &optionsModel);
AddWallet(wallet); 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); RemoveWallet(wallet, std::nullopt);
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress); EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel()); editAddressDialog.setModel(walletModel.getAddressTableModel());

View File

@ -135,7 +135,8 @@ void TestGUI(interfaces::Node& node)
TransactionView transactionView; TransactionView transactionView;
OptionsModel optionsModel(node); OptionsModel optionsModel(node);
ClientModel clientModel(node, &optionsModel); 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); sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel); transactionView.setModel(&walletModel);

View File

@ -11,6 +11,8 @@
#include <qt/guiutil.h> #include <qt/guiutil.h>
#include <qt/walletmodel.h> #include <qt/walletmodel.h>
#include <coinjoin/client.h>
#include <node/context.h>
#include <interfaces/handler.h> #include <interfaces/handler.h>
#include <interfaces/node.h> #include <interfaces/node.h>
#include <util/string.h> #include <util/string.h>
@ -228,7 +230,7 @@ void CreateWalletActivity::createWallet()
} }
QTimer::singleShot(500, worker(), [this, name, flags] { QTimer::singleShot(500, worker(), [this, name, flags] {
std::unique_ptr<interfaces::Wallet> wallet = node().walletLoader().createWallet(name, m_passphrase, flags, m_error_message, m_warning_message); std::unique_ptr<interfaces::Wallet> 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)); 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 <b>%1</b>...").arg(name.toHtmlEscaped())); showProgressDialog(tr("Opening Wallet <b>%1</b>...").arg(name.toHtmlEscaped()));
QTimer::singleShot(0, worker(), [this, path] { QTimer::singleShot(0, worker(), [this, path] {
std::unique_ptr<interfaces::Wallet> wallet = node().walletLoader().loadWallet(path, m_error_message, m_warning_message); std::unique_ptr<interfaces::Wallet> wallet = node().walletLoader().loadWallet(*::coinJoinClientManagers, path, m_error_message, m_warning_message);
if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet)); if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));

View File

@ -4,17 +4,19 @@
#include <node/context.h> #include <node/context.h>
#include <validation.h> #include <validation.h>
#ifdef ENABLE_WALLET #include <coinjoin/context.h>
#include <coinjoin/client.h>
#include <coinjoin/options.h>
#include <wallet/rpcwallet.h>
#endif // ENABLE_WALLET
#include <coinjoin/server.h> #include <coinjoin/server.h>
#include <rpc/blockchain.h> #include <rpc/blockchain.h>
#include <rpc/server.h> #include <rpc/server.h>
#include <rpc/util.h> #include <rpc/util.h>
#include <util/strencodings.h> #include <util/strencodings.h>
#ifdef ENABLE_WALLET
#include <coinjoin/client.h>
#include <coinjoin/options.h>
#include <wallet/rpcwallet.h>
#endif // ENABLE_WALLET
#include <univalue.h> #include <univalue.h>
#ifdef ENABLE_WALLET #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") { 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."); 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."); throw JSONRPCError(RPC_INTERNAL_ERROR, "Mixing has been started already.");
} }
const NodeContext& node = EnsureAnyNodeContext(request.context); const NodeContext& node = EnsureAnyNodeContext(request.context);
CTxMemPool& mempool = EnsureMemPool(node); CTxMemPool& mempool = EnsureMemPool(node);
CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(node); CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(node);
bool result = it->second->DoAutomaticDenominating(*node.connman, fee_estimator, mempool); bool result = cj_clientman->DoAutomaticDenominating(*node.connman, fee_estimator, mempool);
return "Mixing " + (result ? "started successfully" : ("start failed: " + it->second->GetStatuses().original + ", will retry")); return "Mixing " + (result ? "started successfully" : ("start failed: " + cj_clientman->GetStatuses().original + ", will retry"));
} }
if (request.params[0].get_str() == "stop") { if (request.params[0].get_str() == "stop") {
it->second->StopMixing(); cj_clientman->StopMixing();
return "Mixing was stopped"; return "Mixing was stopped";
} }
if (request.params[0].get_str() == "reset") { if (request.params[0].get_str() == "reset") {
it->second->ResetPool(); cj_clientman->ResetPool();
return "Mixing was reset"; return "Mixing was reset";
} }
@ -143,25 +146,26 @@ static UniValue getcoinjoininfo(const JSONRPCRequest& request)
}.Check(request); }.Check(request);
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
const NodeContext& node = EnsureAnyNodeContext(request.context);
if (fMasternodeMode) { if (fMasternodeMode) {
coinJoinServer->GetJsonInfo(obj); node.cj_ctx->server->GetJsonInfo(obj);
return obj; return obj;
} }
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
CCoinJoinClientOptions::GetJsonInfo(obj); CCoinJoinClientOptions::GetJsonInfo(obj);
obj.pushKV("queue_size", coinJoinClientQueueManager->GetQueueSize()); obj.pushKV("queue_size", node.cj_ctx->queueman->GetQueueSize());
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
if (!wallet) { if (!wallet) {
return obj; 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("keys_left", wallet->nKeysLeftSinceAutoBackup);
obj.pushKV("warnings", wallet->nKeysLeftSinceAutoBackup < COINJOIN_KEYS_THRESHOLD_WARNING obj.pushKV("warnings", wallet->nKeysLeftSinceAutoBackup < COINJOIN_KEYS_THRESHOLD_WARNING

View File

@ -81,7 +81,8 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, 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 // Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE); CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@ -153,7 +154,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
auto connman = std::make_unique<CConnmanTest>(0x1337, 0x1337, *m_node.addrman); auto connman = std::make_unique<CConnmanTest>(0x1337, 0x1337, *m_node.addrman);
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, 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(); const Consensus::Params& consensusParams = Params().GetConsensus();
constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS; 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<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, 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(); banman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE); CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@ -274,7 +277,8 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, 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(); banman->ClearBanned();
gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number 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<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, 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(); banman->ClearBanned();
int64_t nStartTime = GetTime(); int64_t nStartTime = GetTime();

View File

@ -58,6 +58,7 @@
#include <coinjoin/client.h> #include <coinjoin/client.h>
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
#include <coinjoin/coinjoin.h> #include <coinjoin/coinjoin.h>
#include <coinjoin/context.h>
#include <coinjoin/server.h> #include <coinjoin/server.h>
#include <evo/cbtx.h> #include <evo/cbtx.h>
#include <evo/creditpool.h> #include <evo/creditpool.h>
@ -103,7 +104,7 @@ void DashTestSetup(NodeContext& node)
{ {
CChainState& chainstate = Assert(node.chainman)->ActiveChainstate(); CChainState& chainstate = Assert(node.chainman)->ActiveChainstate();
::coinJoinServer = std::make_unique<CCoinJoinServer>(chainstate, *node.connman, *node.mempool, *::masternodeSync); node.cj_ctx = std::make_unique<CJContext>(chainstate, *node.connman, *node.mempool, *::masternodeSync, /* relay_txes */ true);
::deterministicMNManager = std::make_unique<CDeterministicMNManager>(chainstate, *node.connman, *node.evodb); ::deterministicMNManager = std::make_unique<CDeterministicMNManager>(chainstate, *node.connman, *node.evodb);
node.llmq_ctx = std::make_unique<LLMQContext>(chainstate, *node.connman, *node.evodb, *sporkManager, *node.mempool, node.peerman, true, false); node.llmq_ctx = std::make_unique<LLMQContext>(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->Stop();
node.llmq_ctx.reset(); node.llmq_ctx.reset();
::deterministicMNManager.reset(); ::deterministicMNManager.reset();
::coinJoinServer.reset(); node.cj_ctx.reset();
} }
BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args) BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
@ -205,9 +206,6 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
::sporkManager = std::make_unique<CSporkManager>(); ::sporkManager = std::make_unique<CSporkManager>();
::governance = std::make_unique<CGovernanceManager>(); ::governance = std::make_unique<CGovernanceManager>();
::masternodeSync = std::make_unique<CMasternodeSync>(*m_node.connman, *::governance); ::masternodeSync = std::make_unique<CMasternodeSync>(*m_node.connman, *::governance);
#ifdef ENABLE_WALLET
::coinJoinClientQueueManager = std::make_unique<CCoinJoinClientQueueManager>(*m_node.connman, *::masternodeSync);
#endif // ENABLE_WALLET
m_node.creditPoolManager = std::make_unique<CCreditPoolManager>(*m_node.evodb); m_node.creditPoolManager = std::make_unique<CCreditPoolManager>(*m_node.evodb);
@ -224,9 +222,6 @@ ChainTestingSetup::~ChainTestingSetup()
StopScriptCheckWorkerThreads(); StopScriptCheckWorkerThreads();
GetMainSignals().FlushBackgroundCallbacks(); GetMainSignals().FlushBackgroundCallbacks();
GetMainSignals().UnregisterBackgroundSignalScheduler(); GetMainSignals().UnregisterBackgroundSignalScheduler();
#ifdef ENABLE_WALLET
::coinJoinClientQueueManager.reset();
#endif // ENABLE_WALLET
::masternodeSync.reset(); ::masternodeSync.reset();
::governance.reset(); ::governance.reset();
::sporkManager.reset(); ::sporkManager.reset();
@ -261,8 +256,8 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
m_node.banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); m_node.banman = std::make_unique<BanMan>(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.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, *m_node.scheduler, *m_node.chainman, *m_node.mempool, *governance,
false); m_node.cj_ctx, m_node.llmq_ctx, false);
{ {
CConnman::Options options; CConnman::Options options;
options.m_msgproc = m_node.peerman.get(); options.m_msgproc = m_node.peerman.get();

View File

@ -46,7 +46,7 @@ public:
// Dash Specific Wallet Init // Dash Specific Wallet Init
void AutoLockMasternodeCollaterals() const override; void AutoLockMasternodeCollaterals() const override;
void InitCoinJoinSettings() const override; void InitCoinJoinSettings(const CJClientManager& clientman) const override;
bool InitAutoBackup() 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); CCoinJoinClientOptions::SetEnabled(!GetWallets().empty() ? gArgs.GetBoolArg("-enablecoinjoin", true) : false);
if (!CCoinJoinClientOptions::IsEnabled()) { if (!CCoinJoinClientOptions::IsEnabled()) {
@ -207,10 +207,12 @@ void WalletInit::InitCoinJoinSettings() const
} }
bool fAutoStart = gArgs.GetBoolArg("-coinjoinautostart", DEFAULT_COINJOIN_AUTOSTART); bool fAutoStart = gArgs.GetBoolArg("-coinjoinautostart", DEFAULT_COINJOIN_AUTOSTART);
for (auto& pwallet : GetWallets()) { for (auto& pwallet : GetWallets()) {
auto manager = clientman.Get(*pwallet);
assert(manager != nullptr);
if (pwallet->IsLocked()) { if (pwallet->IsLocked()) {
coinJoinClientManagers.at(pwallet->GetName())->StopMixing(); manager->StopMixing();
} else if (fAutoStart) { } else if (fAutoStart) {
coinJoinClientManagers.at(pwallet->GetName())->StartMixing(); manager->StartMixing();
} }
} }
LogPrintf("CoinJoin: autostart=%d, multisession=%d," /* Continued */ LogPrintf("CoinJoin: autostart=%d, multisession=%d," /* Continued */

View File

@ -123,52 +123,54 @@ WalletTxOut MakeWalletTxOut(const CWallet& wallet,
namespace CoinJoin = interfaces::CoinJoin; namespace CoinJoin = interfaces::CoinJoin;
class CoinJoinImpl : public CoinJoin::Client class CoinJoinImpl : public CoinJoin::Client
{ {
std::shared_ptr<CCoinJoinClientManager> m_manager; CCoinJoinClientManager& m_manager;
public: public:
CoinJoinImpl(const std::shared_ptr<CWallet>& wallet) : m_manager(coinJoinClientManagers.at(wallet->GetName())) {} CoinJoinImpl(const CJClientManager& clientman, const std::shared_ptr<CWallet>& wallet)
: m_manager(*Assert(clientman.Get(*wallet))) {}
void resetCachedBlocks() override void resetCachedBlocks() override
{ {
m_manager->nCachedNumBlocks = std::numeric_limits<int>::max(); m_manager.nCachedNumBlocks = std::numeric_limits<int>::max();
} }
void resetPool() override void resetPool() override
{ {
m_manager->ResetPool(); m_manager.ResetPool();
} }
void disableAutobackups() override void disableAutobackups() override
{ {
m_manager->fCreateAutoBackups = false; m_manager.fCreateAutoBackups = false;
} }
int getCachedBlocks() override int getCachedBlocks() override
{ {
return m_manager->nCachedNumBlocks; return m_manager.nCachedNumBlocks;
} }
std::string getSessionDenoms() override std::string getSessionDenoms() override
{ {
return m_manager->GetSessionDenoms(); return m_manager.GetSessionDenoms();
} }
void setCachedBlocks(int nCachedBlocks) override void setCachedBlocks(int nCachedBlocks) override
{ {
m_manager->nCachedNumBlocks = nCachedBlocks; m_manager.nCachedNumBlocks = nCachedBlocks;
} }
bool isMixing() override bool isMixing() override
{ {
return m_manager->IsMixing(); return m_manager.IsMixing();
} }
bool startMixing() override bool startMixing() override
{ {
return m_manager->StartMixing(); return m_manager.StartMixing();
} }
void stopMixing() override void stopMixing() override
{ {
m_manager->StopMixing(); m_manager.StopMixing();
} }
}; };
class WalletImpl : public Wallet class WalletImpl : public Wallet
{ {
public: public:
explicit WalletImpl(const std::shared_ptr<CWallet>& wallet, const CJClientManager& clientman) : m_wallet(wallet), m_coinjoin(clientman, wallet) {}
explicit WalletImpl(const std::shared_ptr<CWallet>& wallet) : m_wallet(wallet), m_coinjoin(wallet) {}
void markDirty() override void markDirty() override
{ {
@ -629,7 +631,7 @@ public:
void setMockTime(int64_t time) override { return SetMockTime(time); } void setMockTime(int64_t time) override { return SetMockTime(time); }
//! WalletLoader methods //! WalletLoader methods
std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) override std::unique_ptr<Wallet> createWallet(const CJClientManager& client_man, const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) override
{ {
std::shared_ptr<CWallet> wallet; std::shared_ptr<CWallet> wallet;
DatabaseOptions options; DatabaseOptions options;
@ -637,14 +639,14 @@ public:
options.require_create = true; options.require_create = true;
options.create_flags = wallet_creation_flags; options.create_flags = wallet_creation_flags;
options.create_passphrase = passphrase; 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<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override std::unique_ptr<Wallet> loadWallet(const CJClientManager& client_man, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
{ {
DatabaseOptions options; DatabaseOptions options;
DatabaseStatus status; DatabaseStatus status;
options.require_existing = true; 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 std::string getWalletDir() override
{ {
@ -662,7 +664,7 @@ public:
{ {
std::vector<std::unique_ptr<Wallet>> wallets; std::vector<std::unique_ptr<Wallet>> wallets;
for (const auto& wallet : GetWallets()) { for (const auto& wallet : GetWallets()) {
wallets.emplace_back(MakeWallet(wallet)); wallets.emplace_back(MakeWallet(wallet, *::coinJoinClientManagers));
} }
return wallets; return wallets;
} }
@ -680,7 +682,7 @@ public:
} // namespace wallet } // namespace wallet
namespace interfaces { namespace interfaces {
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? std::make_unique<wallet::WalletImpl>(wallet) : nullptr; } std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet, const CJClientManager& clientman) { return wallet ? std::make_unique<wallet::WalletImpl>(wallet, clientman) : nullptr; }
std::unique_ptr<WalletLoader> MakeWalletLoader(Chain& chain, ArgsManager& args) { std::unique_ptr<WalletLoader> MakeWalletLoader(Chain& chain, ArgsManager& args) {
return std::make_unique<wallet::WalletLoaderImpl>(chain, args); return std::make_unique<wallet::WalletLoaderImpl>(chain, args);
} }

View File

@ -141,9 +141,10 @@ void FlushWallets()
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) { for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
if (CCoinJoinClientOptions::IsEnabled()) { if (CCoinJoinClientOptions::IsEnabled()) {
// Stop CoinJoin, release keys // Stop CoinJoin, release keys
auto it = coinJoinClientManagers.find(pwallet->GetName()); auto cj_clientman = ::coinJoinClientManagers->Get(*pwallet);
it->second->ResetPool(); assert(cj_clientman != nullptr);
it->second->StopMixing(); cj_clientman->ResetPool();
cj_clientman->StopMixing();
} }
pwallet->Flush(); pwallet->Flush();
} }

View File

@ -207,8 +207,8 @@ public:
BOOST_FIXTURE_TEST_CASE(coinjoin_manager_start_stop_tests, CTransactionBuilderTestSetup) BOOST_FIXTURE_TEST_CASE(coinjoin_manager_start_stop_tests, CTransactionBuilderTestSetup)
{ {
BOOST_CHECK_EQUAL(coinJoinClientManagers.size(), 1); BOOST_CHECK_EQUAL(::coinJoinClientManagers->raw().size(), 1);
auto& cj_man = coinJoinClientManagers.begin()->second; auto& cj_man = ::coinJoinClientManagers->raw().begin()->second;
BOOST_CHECK_EQUAL(cj_man->IsMixing(), false); BOOST_CHECK_EQUAL(cj_man->IsMixing(), false);
BOOST_CHECK_EQUAL(cj_man->StartMixing(), true); BOOST_CHECK_EQUAL(cj_man->StartMixing(), true);
BOOST_CHECK_EQUAL(cj_man->IsMixing(), true); BOOST_CHECK_EQUAL(cj_man->IsMixing(), true);

View File

@ -119,9 +119,9 @@ bool AddWallet(const std::shared_ptr<CWallet>& wallet)
} }
wallet->ConnectScriptPubKeyManNotifiers(); wallet->ConnectScriptPubKeyManNotifiers();
wallet->AutoLockMasternodeCollaterals(); wallet->AutoLockMasternodeCollaterals();
assert(::masternodeSync != nullptr); assert(::masternodeSync != nullptr && ::coinJoinClientManagers != nullptr);
coinJoinClientManagers.emplace(std::make_pair(wallet->GetName(), std::make_shared<CCoinJoinClientManager>(*wallet, *::masternodeSync))); ::coinJoinClientManagers->Add(*wallet);
g_wallet_init_interface.InitCoinJoinSettings(); g_wallet_init_interface.InitCoinJoinSettings(*::coinJoinClientManagers);
return true; return true;
} }
@ -140,9 +140,10 @@ bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> lo
if (i == vpwallets.end()) return false; if (i == vpwallets.end()) return false;
vpwallets.erase(i); vpwallets.erase(i);
} }
auto it = coinJoinClientManagers.find(wallet->GetName());
coinJoinClientManagers.erase(it); assert(::coinJoinClientManagers != nullptr);
g_wallet_init_interface.InitCoinJoinSettings(); ::coinJoinClientManagers->Remove(name);
g_wallet_init_interface.InitCoinJoinSettings(*::coinJoinClientManagers);
// Write the wallet setting // Write the wallet setting
UpdateWalletSetting(chain, name, load_on_start, warnings); UpdateWalletSetting(chain, name, load_on_start, warnings);
@ -1639,10 +1640,9 @@ void CWallet::UnsetBlankWalletFlag(WalletBatch& batch)
void CWallet::NewKeyPoolCallback() void CWallet::NewKeyPoolCallback()
{ {
auto it = coinJoinClientManagers.find(GetName()); assert(::coinJoinClientManagers != nullptr);
if (it != coinJoinClientManagers.end()) { auto cj_clientman = ::coinJoinClientManagers->Get(*this);
it->second->StopMixing(); if (cj_clientman != nullptr) cj_clientman->StopMixing();
}
nKeysLeftSinceAutoBackup = 0; nKeysLeftSinceAutoBackup = 0;
} }
@ -4805,13 +4805,13 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
walletInstance->GetDatabase().IncrementUpdateCounter(); walletInstance->GetDatabase().IncrementUpdateCounter();
} }
assert(::masternodeSync != nullptr); assert(::masternodeSync != nullptr && ::coinJoinClientManagers != nullptr);
coinJoinClientManagers.emplace(std::make_pair(walletInstance->GetName(), std::make_shared<CCoinJoinClientManager>(*walletInstance, *::masternodeSync))); ::coinJoinClientManagers->Add(*walletInstance);
{ {
LOCK(cs_wallets); LOCK(cs_wallets);
for (auto& load_wallet : g_load_wallet_fns) { for (auto& load_wallet : g_load_wallet_fns) {
load_wallet(interfaces::MakeWallet(walletInstance)); load_wallet(interfaces::MakeWallet(walletInstance, *::coinJoinClientManagers));
} }
} }

View File

@ -6,6 +6,7 @@
#define BITCOIN_WALLETINITINTERFACE_H #define BITCOIN_WALLETINITINTERFACE_H
class ArgsManager; class ArgsManager;
class CJClientManager;
struct NodeContext; struct NodeContext;
@ -22,7 +23,7 @@ public:
// Dash Specific WalletInitInterface // Dash Specific WalletInitInterface
virtual void AutoLockMasternodeCollaterals() const = 0; virtual void AutoLockMasternodeCollaterals() const = 0;
virtual void InitCoinJoinSettings() const = 0; virtual void InitCoinJoinSettings(const CJClientManager& clientman) const = 0;
virtual bool InitAutoBackup() const = 0; virtual bool InitAutoBackup() const = 0;
virtual ~WalletInitInterface() {} virtual ~WalletInitInterface() {}

View File

@ -65,6 +65,8 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
"logging -> util/system -> stacktraces -> logging" "logging -> util/system -> stacktraces -> logging"
"logging -> util/system -> util/getuniquepath -> random -> logging" "logging -> util/system -> util/getuniquepath -> random -> logging"
"coinjoin/client -> coinjoin/util -> wallet/wallet -> coinjoin/client" "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/appearancewidget -> qt/guiutil -> qt/optionsdialog -> qt/appearancewidget"
"qt/guiutil -> qt/optionsdialog -> qt/optionsmodel -> qt/guiutil" "qt/guiutil -> qt/optionsdialog -> qt/optionsmodel -> qt/guiutil"