LCOV - code coverage report
Current view: top level - src/coinjoin - util.h (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 10 11 90.9 %
Date: 2026-06-25 07:23:51 Functions: 8 15 53.3 %

          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_UTIL_H
       6             : #define BITCOIN_COINJOIN_UTIL_H
       7             : 
       8             : #include <wallet/coincontrol.h>
       9             : #include <wallet/wallet.h>
      10             : 
      11             : class CTransactionBuilder;
      12             : struct bilingual_str;
      13             : 
      14             : class CKeyHolder
      15             : {
      16             : private:
      17             :     wallet::ReserveDestination reserveDestination;
      18             :     CTxDestination dest;
      19             : 
      20             : public:
      21             :     explicit CKeyHolder(wallet::CWallet* pwalletIn);
      22             :     CKeyHolder(CKeyHolder&&) = delete;
      23             :     CKeyHolder& operator=(CKeyHolder&&) = delete;
      24             :     void KeepKey();
      25             :     void ReturnKey();
      26             : 
      27             :     [[nodiscard]] CScript GetScriptForDestination() const;
      28             : };
      29             : 
      30             : class CKeyHolderStorage
      31             : {
      32             : private:
      33             :     mutable Mutex cs_storage;
      34             :     std::vector<std::unique_ptr<CKeyHolder> > storage GUARDED_BY(cs_storage);
      35             : 
      36             : public:
      37             :     CScript AddKey(wallet::CWallet* pwalletIn) EXCLUSIVE_LOCKS_REQUIRED(!cs_storage);
      38             :     void KeepAll() EXCLUSIVE_LOCKS_REQUIRED(!cs_storage);
      39             :     void ReturnAll() EXCLUSIVE_LOCKS_REQUIRED(!cs_storage);
      40             : };
      41             : 
      42             : /**
      43             :  * @brief Used by CTransactionBuilder to represent its transaction outputs.
      44             :  * It creates a ReserveDestination for the given CWallet as destination.
      45             :  */
      46             : class CTransactionBuilderOutput
      47             : {
      48             :     /// Used for amount updates
      49             :     CTransactionBuilder* pTxBuilder{nullptr};
      50             :     /// Reserve key where the amount of this output will end up
      51             :     wallet::ReserveDestination dest;
      52             :     /// Amount this output will receive
      53             :     CAmount nAmount{0};
      54             :     /// ScriptPubKey of this output
      55             :     CScript script;
      56             : 
      57             : public:
      58             :     CTransactionBuilderOutput(CTransactionBuilder* pTxBuilderIn, wallet::CWallet& wallet, CAmount nAmountIn);
      59             :     CTransactionBuilderOutput(CTransactionBuilderOutput&&) = delete;
      60             :     CTransactionBuilderOutput& operator=(CTransactionBuilderOutput&&) = delete;
      61             :     /// Get the scriptPubKey of this output
      62         203 :     [[nodiscard]] CScript GetScript() const { return script; }
      63             :     /// Get the amount of this output
      64        5363 :     [[nodiscard]] CAmount GetAmount() const { return nAmount; }
      65             :     /// Try update the amount of this output. Returns true if it was successful and false if not (e.g. insufficient amount left).
      66             :     bool UpdateAmount(CAmount nAmount);
      67             :     /// Tell the wallet to remove the key used by this output from the keypool
      68         101 :     void KeepKey() { dest.KeepDestination(); }
      69             :     /// Tell the wallet to return the key used by this output to the keypool
      70           0 :     void ReturnKey() { dest.ReturnDestination(); }
      71             : };
      72             : 
      73             : /**
      74             :  * @brief Enables simple transaction generation for a given CWallet object. The resulting
      75             :  * transaction's inputs are defined by the given CompactTallyItem. The outputs are
      76             :  * defined by CTransactionBuilderOutput.
      77             :  */
      78             : class CTransactionBuilder
      79             : {
      80             :     /// Wallet the transaction will be build for
      81             :     wallet::CWallet& m_wallet;
      82             :     /// See CTransactionBuilder() for initialization
      83             :     wallet::CCoinControl coinControl;
      84             :     /// Dummy since we anyway use tallyItem's destination as change destination in coincontrol.
      85             :     /// Its a member just to make sure ReturnKey can be called in destructor just in case it gets generated/kept
      86             :     /// somewhere in CWallet code.
      87             :     wallet::ReserveDestination dummyReserveDestination;
      88             :     /// Contains all utxos available to generate this transactions. They are all from the same address.
      89             :     wallet::CompactTallyItem tallyItem;
      90             :     /// Contains the number of bytes required for a transaction with only the inputs of tallyItems, no outputs
      91             :     int nBytesBase{0};
      92             :     /// Contains the number of bytes required to add one output
      93             :     int nBytesOutput{0};
      94             :     /// Call KeepKey for all keys in destructor if fKeepKeys is true, call ReturnKey for all key if its false.
      95             :     bool fKeepKeys{false};
      96             :     /// Protect vecOutputs
      97             :     mutable Mutex cs_outputs;
      98             :     /// Contains all outputs already added to the transaction
      99             :     std::vector<std::unique_ptr<CTransactionBuilderOutput>> vecOutputs GUARDED_BY(cs_outputs);
     100             :     /// Needed by CTransactionBuilderOutput::UpdateAmount to lock cs_outputs
     101             :     friend class CTransactionBuilderOutput;
     102             : 
     103             : public:
     104             :     CTransactionBuilder(wallet::CWallet& wallet, const wallet::CompactTallyItem& tallyItemIn);
     105             :     ~CTransactionBuilder();
     106             :     /// Check it would be possible to add a single output with the amount nAmount. Returns true if its possible and false if not.
     107             :     bool CouldAddOutput(CAmount nAmountOutput) const EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);
     108             :     /// Check if its possible to add multiple outputs as vector of amounts. Returns true if its possible to add all of them and false if not.
     109             :     bool CouldAddOutputs(const std::vector<CAmount>& vecOutputAmounts) const EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);
     110             :     /// Add an output with the amount nAmount. Returns a pointer to the output if it could be added and nullptr if not due to insufficient amount left.
     111             :     CTransactionBuilderOutput* AddOutput(CAmount nAmountOutput = 0) EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);
     112             :     /// Get amount we had available when we started
     113         119 :     CAmount GetAmountInitial() const { return tallyItem.nAmount; }
     114             :     /// Get the amount currently left to add more outputs. Does respect fees.
     115          11 :     CAmount GetAmountLeft() const EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs)
     116          11 :         { return GetAmountInitial() - GetAmountUsed() - GetFee(GetBytesTotal()); }
     117             :     /// Check if an amounts should be considered as dust
     118             :     bool IsDust(CAmount nAmount) const;
     119             :     /// Get the total number of added outputs
     120           5 :     int CountOutputs() const EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs)
     121             :     {
     122           5 :         LOCK(cs_outputs);
     123           5 :         return vecOutputs.size();
     124           5 :     }
     125             :     /// Create and Commit the transaction to the wallet
     126             :     bool Commit(bilingual_str& strResult) EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);
     127             :     /// Convert to a string
     128             :     std::string ToString() const EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);
     129             : 
     130             : private:
     131             :     /// Clear the output vector and keep/return the included keys depending on the value of fKeepKeys
     132             :     void Clear() EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);
     133             :     /// Get the total number of bytes used already by this transaction
     134             :     unsigned int GetBytesTotal() const EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);
     135             :     /// Helper to calculate static amount left by simply subtracting an used amount and a fee from a provided initial amount.
     136             :     static CAmount GetAmountLeft(CAmount nAmountInitial, CAmount nAmountUsed, CAmount nFee);
     137             :     /// Get the amount currently used by added outputs. Does not include fees.
     138             :     CAmount GetAmountUsed() const EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);
     139             :     /// Get fees based on the number of bytes and the feerate set in CoinControl.
     140             :     /// NOTE: To get the total transaction fee this should only be called once with the total number of bytes for the transaction to avoid
     141             :     /// calling CFeeRate::GetFee multiple times with subtotals as this may add rounding errors with each further call.
     142             :     CAmount GetFee(unsigned int nBytes) const;
     143             :     /// Helper to get GetSizeOfCompactSizeDiff(vecOutputs.size(), vecOutputs.size() + nAdd)
     144             :     int GetSizeOfCompactSizeDiff(size_t nAdd) const EXCLUSIVE_LOCKS_REQUIRED(!cs_outputs);
     145             : };
     146             : 
     147             : #endif // BITCOIN_COINJOIN_UTIL_H

Generated by: LCOV version 1.16