LCOV - code coverage report
Current view: top level - src/coinjoin - client.h (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 17 18 94.4 %
Date: 2026-06-25 07:23:51 Functions: 12 16 75.0 %

          Line data    Source code
       1             : // Copyright (c) 2014-2025 The Dash Core developers
       2             : // Distributed under the MIT/X11 software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #ifndef BITCOIN_COINJOIN_CLIENT_H
       6             : #define BITCOIN_COINJOIN_CLIENT_H
       7             : 
       8             : #include <coinjoin/coinjoin.h>
       9             : #include <coinjoin/util.h>
      10             : #include <evo/types.h>
      11             : #include <util/translation.h>
      12             : 
      13             : #include <atomic>
      14             : #include <deque>
      15             : #include <memory>
      16             : #include <ranges>
      17             : #include <utility>
      18             : 
      19             : class CCoinJoinClientManager;
      20             : class CConnman;
      21             : class CDeterministicMNManager;
      22             : class ChainstateManager;
      23             : class CMasternodeMetaMan;
      24             : class CMasternodeSync;
      25             : class CNode;
      26             : class CTxMemPool;
      27             : 
      28             : class UniValue;
      29             : 
      30             : class CPendingDsaRequest
      31             : {
      32             : private:
      33             :     static constexpr int TIMEOUT = 15;
      34             : 
      35             :     uint256 proTxHash;
      36             :     CCoinJoinAccept dsa;
      37           4 :     int64_t nTimeCreated{0};
      38             : 
      39             : public:
      40          12 :     CPendingDsaRequest() = default;
      41             : 
      42           2 :     CPendingDsaRequest(uint256 proTxHash_, CCoinJoinAccept dsa_) :
      43           1 :         proTxHash(std::move(proTxHash_)),
      44           1 :         dsa(std::move(dsa_)),
      45           1 :         nTimeCreated(GetTime())
      46           1 :     {
      47           2 :     }
      48             : 
      49           2 :     [[nodiscard]] uint256 GetProTxHash() const { return proTxHash; }
      50           2 :     [[nodiscard]] CCoinJoinAccept GetDSA() const { return dsa; }
      51           4 :     [[nodiscard]] bool IsExpired() const { return GetTime() - nTimeCreated > TIMEOUT; }
      52             : 
      53           5 :     friend bool operator==(const CPendingDsaRequest& a, const CPendingDsaRequest& b)
      54             :     {
      55           5 :         return a.proTxHash == b.proTxHash && a.dsa == b.dsa;
      56             :     }
      57           3 :     friend bool operator!=(const CPendingDsaRequest& a, const CPendingDsaRequest& b)
      58             :     {
      59           3 :         return !(a == b);
      60             :     }
      61           2 :     explicit operator bool() const
      62             :     {
      63           2 :         return *this != CPendingDsaRequest();
      64           0 :     }
      65             : };
      66             : 
      67             : class CCoinJoinClientSession : public CCoinJoinBaseSession
      68             : {
      69             : private:
      70             :     const std::shared_ptr<wallet::CWallet> m_wallet;
      71             :     CCoinJoinClientManager& m_clientman;
      72             :     CDeterministicMNManager& m_dmnman;
      73             :     CMasternodeMetaMan& m_mn_metaman;
      74             :     const CMasternodeSync& m_mn_sync;
      75             :     const llmq::CInstantSendManager& m_isman;
      76             :     std::vector<COutPoint> vecOutPointLocked;
      77             : 
      78             :     bilingual_str strLastMessage;
      79             :     bilingual_str strAutoDenomResult;
      80             : 
      81             :     CDeterministicMNCPtr mixingMasternode;
      82             :     CMutableTransaction txMyCollateral; // client side collateral
      83             :     CPendingDsaRequest pendingDsaRequest;
      84             : 
      85             :     CKeyHolderStorage keyHolderStorage; // storage for keys used in PrepareDenominate
      86             : 
      87             :     /// Create denominations
      88             :     bool CreateDenominated(CAmount nBalanceToDenominate);
      89             :     bool CreateDenominated(CAmount nBalanceToDenominate, const wallet::CompactTallyItem& tallyItem, bool fCreateMixingCollaterals)
      90             :         EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet);
      91             : 
      92             :     /// Split up large inputs or make fee sized inputs
      93             :     bool MakeCollateralAmounts();
      94             :     bool MakeCollateralAmounts(const wallet::CompactTallyItem& tallyItem, bool fTryDenominated)
      95             :         EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet);
      96             : 
      97             :     bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason)
      98             :         EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet);
      99             : 
     100             :     bool JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
     101             :     bool StartNewQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
     102             : 
     103             :     /// step 0: select denominated inputs and txouts
     104             :     bool SelectDenominate(std::string& strErrorRet, std::vector<CTxDSIn>& vecTxDSInRet);
     105             :     /// step 1: prepare denominated inputs and outputs
     106             :     bool PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, const std::vector<CTxDSIn>& vecTxDSIn,
     107             :                            std::vector<std::pair<CTxDSIn, CTxOut>>& vecPSInOutPairsRet, bool fDryRun = false)
     108             :         EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet);
     109             :     /// step 2: send denominated inputs and outputs prepared in step 1
     110             :     bool SendDenominate(const std::vector<std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin);
     111             : 
     112             :     /// Process Masternode updates about the progress of mixing
     113             :     void ProcessPoolStateUpdate(CCoinJoinStatusUpdate psssup);
     114             :     // Set the 'state' value, with some logging and capturing when the state changed
     115             :     void SetState(PoolState nStateNew);
     116             : 
     117             :     void CompletedTransaction(PoolMessage nMessageID);
     118             : 
     119             :     /// As a client, check and sign the final transaction
     120             :     bool SignFinalTransaction(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, const CTransaction& finalTransactionNew) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin);
     121             : 
     122             :     void RelayIn(const CCoinJoinEntry& entry, CConnman& connman) const;
     123             : 
     124             :     void SetNull() override EXCLUSIVE_LOCKS_REQUIRED(cs_coinjoin);
     125             : 
     126             : public:
     127             :     explicit CCoinJoinClientSession(const std::shared_ptr<wallet::CWallet>& wallet, CCoinJoinClientManager& clientman,
     128             :                                     CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman,
     129             :                                     const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman);
     130             : 
     131             :     void ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv);
     132             : 
     133             :     void UnlockCoins();
     134             : 
     135             :     void ResetPool() EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin);
     136             : 
     137             :     bilingual_str GetStatus(bool fWaitForBlock) const;
     138             : 
     139             :     bool GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const;
     140             : 
     141             :     /// Passively run mixing in the background according to the configuration in settings
     142             :     bool DoAutomaticDenominating(ChainstateManager& chainman, CConnman& connman, const CTxMemPool& mempool,
     143             :                                  bool fDryRun = false) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin);
     144             : 
     145             :     /// As a client, submit part of a future mixing transaction to a Masternode to start the process
     146             :     bool SubmitDenominate(CConnman& connman);
     147             : 
     148             :     bool ProcessPendingDsaRequest(CConnman& connman);
     149             : 
     150             :     bool CheckTimeout();
     151             : 
     152             :     void GetJsonInfo(UniValue& obj) const;
     153             : };
     154             : 
     155             : /** Used to keep track of current status of mixing pool
     156             :  */
     157             : class CCoinJoinClientManager
     158             : {
     159             : private:
     160             :     const std::shared_ptr<wallet::CWallet> m_wallet;
     161             :     CDeterministicMNManager& m_dmnman;
     162             :     CMasternodeMetaMan& m_mn_metaman;
     163             :     const CMasternodeSync& m_mn_sync;
     164             :     const llmq::CInstantSendManager& m_isman;
     165             :     //! Non-owning pointer; null when relay_txes is disabled (no queue processing).
     166             :     CoinJoinQueueManager* const m_queueman;
     167             : 
     168             :     mutable Mutex cs_deqsessions;
     169             :     // TODO: or map<denom, CCoinJoinClientSession> ??
     170             :     std::deque<CCoinJoinClientSession> deqSessions GUARDED_BY(cs_deqsessions);
     171             : 
     172             :     std::atomic<bool> fMixing{false};
     173             : 
     174             :     int nCachedLastSuccessBlock{0};
     175             :     int nMinBlocksToWait{1}; // how many blocks to wait for after one successful mixing tx in non-multisession mode
     176             :     bilingual_str strAutoDenomResult;
     177             : 
     178             :     // Keep track of current block height
     179             :     int nCachedBlockHeight{0};
     180             : 
     181             :     bool WaitForAnotherBlock() const;
     182             : 
     183             :     // Make sure we have enough keys since last backup
     184             :     bool CheckAutomaticBackup();
     185             : 
     186             : public:
     187             :     int nCachedNumBlocks{std::numeric_limits<int>::max()};    // used for the overview screen
     188             :     bool fCreateAutoBackups{true}; // builtin support for automatic backups
     189             : 
     190             :     CCoinJoinClientManager() = delete;
     191             :     CCoinJoinClientManager(const CCoinJoinClientManager&) = delete;
     192             :     CCoinJoinClientManager& operator=(const CCoinJoinClientManager&) = delete;
     193             :     explicit CCoinJoinClientManager(const std::shared_ptr<wallet::CWallet>& wallet, CDeterministicMNManager& dmnman,
     194             :                                     CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync,
     195             :                                     const llmq::CInstantSendManager& isman, CoinJoinQueueManager* queueman);
     196             :     ~CCoinJoinClientManager();
     197             : 
     198             :     void ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     199             : 
     200             :     bool StartMixing();
     201             :     void StopMixing();
     202             :     bool IsMixing() const;
     203             :     void ResetPool() EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     204             : 
     205             :     std::vector<std::string> GetStatuses() const EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     206             :     std::string GetSessionDenoms() EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     207             : 
     208             :     bool GetMixingMasternodesInfo(std::vector<CDeterministicMNCPtr>& vecDmnsRet) const EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     209             : 
     210             :     /// Passively run mixing in the background according to the configuration in settings
     211             :     bool DoAutomaticDenominating(ChainstateManager& chainman, CConnman& connman, const CTxMemPool& mempool,
     212             :                                  bool fDryRun = false) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     213             : 
     214             :     bool TrySubmitDenominate(const uint256& proTxHash, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     215             :     bool MarkAlreadyJoinedQueueAsTried(CCoinJoinQueue& dsq) const EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     216             :     bool GetQueueItemAndTry(CCoinJoinQueue& dsq) const;
     217             : 
     218             :     void CheckTimeout() EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     219             : 
     220             :     void ProcessPendingDsaRequest(CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     221             : 
     222             :     void AddUsedMasternode(const uint256& proTxHash);
     223             :     CDeterministicMNCPtr GetRandomNotUsedMasternode();
     224             : 
     225             :     void UpdatedSuccessBlock();
     226             : 
     227             :     void UpdatedBlockTip(const CBlockIndex* pindex);
     228             : 
     229             :     void DoMaintenance(ChainstateManager& chainman, CConnman& connman, const CTxMemPool& mempool)
     230             :         EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     231             : 
     232             :     void GetJsonInfo(UniValue& obj) const EXCLUSIVE_LOCKS_REQUIRED(!cs_deqsessions);
     233             : };
     234             : 
     235             : #endif // BITCOIN_COINJOIN_CLIENT_H

Generated by: LCOV version 1.16