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 \
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 \

File diff suppressed because it is too large Load Diff

View File

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

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>
std::unique_ptr<CCoinJoinServer> 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

View File

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

View File

@ -7,6 +7,7 @@
#ifdef ENABLE_WALLET
#include <coinjoin/client.h>
#endif // ENABLE_WALLET
#include <coinjoin/context.h>
#include <dsnotificationinterface.h>
#include <governance/governance.h>
#include <masternode/sync.h>
@ -23,8 +24,9 @@
CDSNotificationInterface::CDSNotificationInterface(CConnman& _connman,
CMasternodeSync& _mn_sync, const std::unique_ptr<CDeterministicMNManager>& _dmnman,
CGovernanceManager& _govman, const std::unique_ptr<LLMQContext>& _llmq_ctx
) : connman(_connman), m_mn_sync(_mn_sync), dmnman(_dmnman), govman(_govman), llmq_ctx(_llmq_ctx) {}
CGovernanceManager& _govman, const std::unique_ptr<LLMQContext>& _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()
{
@ -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

View File

@ -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<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;
// a small helper to initialize current block height in sub-modules on startup
@ -45,6 +47,7 @@ private:
CGovernanceManager& govman;
const std::unique_ptr<LLMQContext>& llmq_ctx;
const std::unique_ptr<CJContext>& cj_ctx;
};
#endif // BITCOIN_DSNOTIFICATIONINTERFACE_H

View File

@ -24,7 +24,7 @@ public:
// Dash Specific WalletInitInterface InitCoinJoinSettings
void AutoLockMasternodeCollaterals() const override {}
void InitCoinJoinSettings() const override {}
void InitCoinJoinSettings(const CJClientManager& clientman) const override {}
bool InitAutoBackup() const override {return true;}
};
@ -74,7 +74,7 @@ const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
namespace interfaces {
std::unique_ptr<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.");
}

View File

@ -68,6 +68,7 @@
#include <validationinterface.h>
#include <masternode/node.h>
#include <coinjoin/context.h>
#ifdef ENABLE_WALLET
#include <coinjoin/client.h>
#include <coinjoin/options.h>
@ -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<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
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
g_txindex = std::make_unique<TxIndex>(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<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
// ********************************************************* 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
}

View File

@ -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<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.
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.
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<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
//! function will be undefined in builds where ENABLE_WALLET is false.

View File

@ -13,16 +13,16 @@
#include <shutdown.h>
#include <validation.h>
#include <util/ranges.h>
#include <coinjoin/context.h>
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<CDeterministicMNCPtr> 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

View File

@ -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

View File

@ -44,6 +44,7 @@
#ifdef ENABLE_WALLET
#include <coinjoin/client.h>
#endif // ENABLE_WALLET
#include <coinjoin/context.h>
#include <coinjoin/server.h>
#include <evo/deterministicmns.h>
@ -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<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. */
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override;
@ -309,6 +311,7 @@ private:
BanMan* const m_banman;
ChainstateManager& m_chainman;
CTxMemPool& m_mempool;
const std::unique_ptr<CJContext>& m_cj_ctx;
const std::unique_ptr<LLMQContext>& m_llmq_ctx;
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,
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,
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_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);

View File

@ -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<PeerManager> make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
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() { }
/** Get statistics from node state */

View File

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

View File

@ -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<LLMQContext> llmq_ctx;
std::unique_ptr<CCreditPoolManager> creditPoolManager;
std::unique_ptr<CJContext> cj_ctx;
std::unique_ptr<CEvoDB> evodb;

View File

@ -14,6 +14,7 @@
#include <qt/qvalidatedlineedit.h>
#include <qt/walletmodel.h>
#include <coinjoin/client.h>
#include <key.h>
#include <key_io.h>
#include <wallet/wallet.h>
@ -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());

View File

@ -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);

View File

@ -11,6 +11,8 @@
#include <qt/guiutil.h>
#include <qt/walletmodel.h>
#include <coinjoin/client.h>
#include <node/context.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <util/string.h>
@ -228,7 +230,7 @@ void CreateWalletActivity::createWallet()
}
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));
@ -299,7 +301,7 @@ void OpenWalletActivity::open(const std::string& path)
showProgressDialog(tr("Opening Wallet <b>%1</b>...").arg(name.toHtmlEscaped()));
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));

View File

@ -4,17 +4,19 @@
#include <node/context.h>
#include <validation.h>
#ifdef ENABLE_WALLET
#include <coinjoin/client.h>
#include <coinjoin/options.h>
#include <wallet/rpcwallet.h>
#endif // ENABLE_WALLET
#include <coinjoin/context.h>
#include <coinjoin/server.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <rpc/util.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>
#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<CWallet> 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

View File

@ -81,7 +81,8 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
const CChainParams& chainparams = Params();
auto connman = std::make_unique<CConnman>(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<CConnmanTest>(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<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
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,
*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<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
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,
*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<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
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,
*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();

View File

@ -58,6 +58,7 @@
#include <coinjoin/client.h>
#endif // ENABLE_WALLET
#include <coinjoin/coinjoin.h>
#include <coinjoin/context.h>
#include <coinjoin/server.h>
#include <evo/cbtx.h>
#include <evo/creditpool.h>
@ -103,7 +104,7 @@ void DashTestSetup(NodeContext& node)
{
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);
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.reset();
::deterministicMNManager.reset();
::coinJoinServer.reset();
node.cj_ctx.reset();
}
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>();
::governance = std::make_unique<CGovernanceManager>();
::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);
@ -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<const
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.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();

View File

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

View File

@ -123,52 +123,54 @@ WalletTxOut MakeWalletTxOut(const CWallet& wallet,
namespace CoinJoin = interfaces::CoinJoin;
class CoinJoinImpl : public CoinJoin::Client
{
std::shared_ptr<CCoinJoinClientManager> m_manager;
CCoinJoinClientManager& m_manager;
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
{
m_manager->nCachedNumBlocks = std::numeric_limits<int>::max();
m_manager.nCachedNumBlocks = std::numeric_limits<int>::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<CWallet>& wallet) : m_wallet(wallet), m_coinjoin(wallet) {}
explicit WalletImpl(const std::shared_ptr<CWallet>& wallet, const CJClientManager& clientman) : m_wallet(wallet), m_coinjoin(clientman, wallet) {}
void markDirty() override
{
@ -629,7 +631,7 @@ public:
void setMockTime(int64_t time) override { return SetMockTime(time); }
//! WalletLoader methods
std::unique_ptr<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;
DatabaseOptions options;
@ -637,14 +639,14 @@ public:
options.require_create = true;
options.create_flags = wallet_creation_flags;
options.create_passphrase = passphrase;
return MakeWallet(CreateWallet(*m_context.chain, name, true /* load_on_start */, options, status, error, warnings));
return MakeWallet(CreateWallet(*m_context.chain, name, true /* load_on_start */, options, status, error, warnings), client_man);
}
std::unique_ptr<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;
DatabaseStatus status;
options.require_existing = true;
return MakeWallet(LoadWallet(*m_context.chain, name, true /* load_on_start */, options, status, error, warnings));
return MakeWallet(LoadWallet(*m_context.chain, name, true /* load_on_start */, options, status, error, warnings), client_man);
}
std::string getWalletDir() override
{
@ -662,7 +664,7 @@ public:
{
std::vector<std::unique_ptr<Wallet>> wallets;
for (const auto& wallet : GetWallets()) {
wallets.emplace_back(MakeWallet(wallet));
wallets.emplace_back(MakeWallet(wallet, *::coinJoinClientManagers));
}
return wallets;
}
@ -680,7 +682,7 @@ public:
} // namespace wallet
namespace interfaces {
std::unique_ptr<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) {
return std::make_unique<wallet::WalletLoaderImpl>(chain, args);
}

View File

@ -141,9 +141,10 @@ void FlushWallets()
for (const std::shared_ptr<CWallet>& 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();
}

View File

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

View File

@ -119,9 +119,9 @@ bool AddWallet(const std::shared_ptr<CWallet>& wallet)
}
wallet->ConnectScriptPubKeyManNotifiers();
wallet->AutoLockMasternodeCollaterals();
assert(::masternodeSync != nullptr);
coinJoinClientManagers.emplace(std::make_pair(wallet->GetName(), std::make_shared<CCoinJoinClientManager>(*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<CWallet>& wallet, std::optional<bool> 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> CWallet::Create(interfaces::Chain& chain, const std::st
walletInstance->GetDatabase().IncrementUpdateCounter();
}
assert(::masternodeSync != nullptr);
coinJoinClientManagers.emplace(std::make_pair(walletInstance->GetName(), std::make_shared<CCoinJoinClientManager>(*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));
}
}

View File

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

View File

@ -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"