LCOV - code coverage report
Current view: top level - src/wallet - spend.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 578 637 90.7 %
Date: 2022-04-21 14:51:19 Functions: 20 20 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 345 410 84.1 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2021 The Bitcoin Core developers
#       2                 :            : // Distributed under the MIT software license, see the accompanying
#       3                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       4                 :            : 
#       5                 :            : #include <consensus/amount.h>
#       6                 :            : #include <consensus/validation.h>
#       7                 :            : #include <interfaces/chain.h>
#       8                 :            : #include <policy/policy.h>
#       9                 :            : #include <script/signingprovider.h>
#      10                 :            : #include <util/check.h>
#      11                 :            : #include <util/fees.h>
#      12                 :            : #include <util/moneystr.h>
#      13                 :            : #include <util/rbf.h>
#      14                 :            : #include <util/translation.h>
#      15                 :            : #include <wallet/coincontrol.h>
#      16                 :            : #include <wallet/fees.h>
#      17                 :            : #include <wallet/receive.h>
#      18                 :            : #include <wallet/spend.h>
#      19                 :            : #include <wallet/transaction.h>
#      20                 :            : #include <wallet/wallet.h>
#      21                 :            : 
#      22                 :            : #include <cmath>
#      23                 :            : 
#      24                 :            : using interfaces::FoundBlock;
#      25                 :            : 
#      26                 :            : namespace wallet {
#      27                 :            : static constexpr size_t OUTPUT_GROUP_MAX_ENTRIES{100};
#      28                 :            : 
#      29                 :            : int GetTxSpendSize(const CWallet& wallet, const CWalletTx& wtx, unsigned int out, bool use_max_sig)
#      30                 :     453842 : {
#      31                 :     453842 :     return CalculateMaximumSignedInputSize(wtx.tx->vout[out], &wallet, use_max_sig);
#      32                 :     453842 : }
#      33                 :            : 
#      34                 :            : int CalculateMaximumSignedInputSize(const CTxOut& txout, const SigningProvider* provider, bool use_max_sig)
#      35                 :     459367 : {
#      36                 :     459367 :     CMutableTransaction txn;
#      37                 :     459367 :     txn.vin.push_back(CTxIn(COutPoint()));
#      38 [ +  + ][ +  + ]:     459367 :     if (!provider || !DummySignInput(*provider, txn.vin[0], txout, use_max_sig)) {
#      39                 :     110253 :         return -1;
#      40                 :     110253 :     }
#      41                 :     349114 :     return GetVirtualTransactionInputSize(txn.vin[0]);
#      42                 :     459367 : }
#      43                 :            : 
#      44                 :            : int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, bool use_max_sig)
#      45                 :     459289 : {
#      46                 :     459289 :     const std::unique_ptr<SigningProvider> provider = wallet->GetSolvingProvider(txout.scriptPubKey);
#      47                 :     459289 :     return CalculateMaximumSignedInputSize(txout, provider.get(), use_max_sig);
#      48                 :     459289 : }
#      49                 :            : 
#      50                 :            : // txouts needs to be in the order of tx.vin
#      51                 :            : TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, const CCoinControl* coin_control)
#      52                 :       5563 : {
#      53                 :       5563 :     CMutableTransaction txNew(tx);
#      54         [ -  + ]:       5563 :     if (!wallet->DummySignTx(txNew, txouts, coin_control)) {
#      55                 :          0 :         return TxSize{-1, -1};
#      56                 :          0 :     }
#      57                 :       5563 :     CTransaction ctx(txNew);
#      58                 :       5563 :     int64_t vsize = GetVirtualTransactionSize(ctx);
#      59                 :       5563 :     int64_t weight = GetTransactionWeight(ctx);
#      60                 :       5563 :     return TxSize{vsize, weight};
#      61                 :       5563 : }
#      62                 :            : 
#      63                 :            : TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const CCoinControl* coin_control)
#      64                 :       5563 : {
#      65                 :       5563 :     std::vector<CTxOut> txouts;
#      66                 :            :     // Look up the inputs. The inputs are either in the wallet, or in coin_control.
#      67         [ +  + ]:      23759 :     for (const CTxIn& input : tx.vin) {
#      68                 :      23759 :         const auto mi = wallet->mapWallet.find(input.prevout.hash);
#      69                 :            :         // Can not estimate size without knowing the input details
#      70         [ +  + ]:      23759 :         if (mi != wallet->mapWallet.end()) {
#      71                 :      23687 :             assert(input.prevout.n < mi->second.tx->vout.size());
#      72                 :          0 :             txouts.emplace_back(mi->second.tx->vout.at(input.prevout.n));
#      73         [ +  - ]:      23687 :         } else if (coin_control) {
#      74                 :         72 :             CTxOut txout;
#      75         [ -  + ]:         72 :             if (!coin_control->GetExternalOutput(input.prevout, txout)) {
#      76                 :          0 :                 return TxSize{-1, -1};
#      77                 :          0 :             }
#      78                 :         72 :             txouts.emplace_back(txout);
#      79                 :         72 :         } else {
#      80                 :          0 :             return TxSize{-1, -1};
#      81                 :          0 :         }
#      82                 :      23759 :     }
#      83                 :       5563 :     return CalculateMaximumSignedTxSize(tx, wallet, txouts, coin_control);
#      84                 :       5563 : }
#      85                 :            : 
#      86                 :            : void AvailableCoins(const CWallet& wallet, std::vector<COutput>& vCoins, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount)
#      87                 :       5986 : {
#      88                 :       5986 :     AssertLockHeld(wallet.cs_wallet);
#      89                 :            : 
#      90                 :       5986 :     vCoins.clear();
#      91                 :       5986 :     CAmount nTotal = 0;
#      92                 :            :     // Either the WALLET_FLAG_AVOID_REUSE flag is not set (in which case we always allow), or we default to avoiding, and only in the case where
#      93                 :            :     // a coin control object is provided, and has the avoid address reuse flag set to false, do we allow already used addresses
#      94 [ +  + ][ +  - ]:       5986 :     bool allow_used_addresses = !wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE) || (coinControl && !coinControl->m_avoid_address_reuse);
#                 [ +  + ]
#      95         [ +  + ]:       5986 :     const int min_depth = {coinControl ? coinControl->m_min_depth : DEFAULT_MIN_DEPTH};
#      96         [ +  + ]:       5986 :     const int max_depth = {coinControl ? coinControl->m_max_depth : DEFAULT_MAX_DEPTH};
#      97         [ +  + ]:       5986 :     const bool only_safe = {coinControl ? !coinControl->m_include_unsafe_inputs : true};
#      98                 :            : 
#      99                 :       5986 :     std::set<uint256> trusted_parents;
#     100         [ +  + ]:       5986 :     for (const auto& entry : wallet.mapWallet)
#     101                 :    1311629 :     {
#     102                 :    1311629 :         const uint256& wtxid = entry.first;
#     103                 :    1311629 :         const CWalletTx& wtx = entry.second;
#     104                 :            : 
#     105         [ +  + ]:    1311629 :         if (wallet.IsTxImmatureCoinBase(wtx))
#     106                 :     409507 :             continue;
#     107                 :            : 
#     108                 :     902122 :         int nDepth = wallet.GetTxDepthInMainChain(wtx);
#     109         [ +  + ]:     902122 :         if (nDepth < 0)
#     110                 :       3696 :             continue;
#     111                 :            : 
#     112                 :            :         // We should not consider coins which aren't at least in our mempool
#     113                 :            :         // It's possible for these to be conflicted via ancestors which we may never be able to detect
#     114 [ +  + ][ +  + ]:     898426 :         if (nDepth == 0 && !wtx.InMempool())
#     115                 :       6300 :             continue;
#     116                 :            : 
#     117                 :     892126 :         bool safeTx = CachedTxIsTrusted(wallet, wtx, trusted_parents);
#     118                 :            : 
#     119                 :            :         // We should not consider coins from transactions that are replacing
#     120                 :            :         // other transactions.
#     121                 :            :         //
#     122                 :            :         // Example: There is a transaction A which is replaced by bumpfee
#     123                 :            :         // transaction B. In this case, we want to prevent creation of
#     124                 :            :         // a transaction B' which spends an output of B.
#     125                 :            :         //
#     126                 :            :         // Reason: If transaction A were initially confirmed, transactions B
#     127                 :            :         // and B' would no longer be valid, so the user would have to create
#     128                 :            :         // a new transaction C to replace B'. However, in the case of a
#     129                 :            :         // one-block reorg, transactions B' and C might BOTH be accepted,
#     130                 :            :         // when the user only wanted one of them. Specifically, there could
#     131                 :            :         // be a 1-block reorg away from the chain where transactions A and C
#     132                 :            :         // were accepted to another chain where B, B', and C were all
#     133                 :            :         // accepted.
#     134 [ +  + ][ +  + ]:     892126 :         if (nDepth == 0 && wtx.mapValue.count("replaces_txid")) {
#                 [ +  + ]
#     135                 :        230 :             safeTx = false;
#     136                 :        230 :         }
#     137                 :            : 
#     138                 :            :         // Similarly, we should not consider coins from transactions that
#     139                 :            :         // have been replaced. In the example above, we would want to prevent
#     140                 :            :         // creation of a transaction A' spending an output of A, because if
#     141                 :            :         // transaction B were initially confirmed, conflicting with A and
#     142                 :            :         // A', we wouldn't want to the user to create a transaction D
#     143                 :            :         // intending to replace A', but potentially resulting in a scenario
#     144                 :            :         // where A, A', and D could all be accepted (instead of just B and
#     145                 :            :         // D, or just A and A' like the user would want).
#     146 [ +  + ][ +  + ]:     892126 :         if (nDepth == 0 && wtx.mapValue.count("replaced_by_txid")) {
#                 [ +  + ]
#     147                 :          2 :             safeTx = false;
#     148                 :          2 :         }
#     149                 :            : 
#     150 [ +  + ][ +  + ]:     892126 :         if (only_safe && !safeTx) {
#     151                 :       3686 :             continue;
#     152                 :       3686 :         }
#     153                 :            : 
#     154 [ +  + ][ +  + ]:     888440 :         if (nDepth < min_depth || nDepth > max_depth) {
#     155                 :       5203 :             continue;
#     156                 :       5203 :         }
#     157                 :            : 
#     158                 :     883237 :         bool tx_from_me = CachedTxIsFromMe(wallet, wtx, ISMINE_ALL);
#     159                 :            : 
#     160         [ +  + ]:    2811570 :         for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
#     161                 :            :             // Only consider selected coins if add_inputs is false
#     162 [ +  + ][ +  + ]:    1928333 :             if (coinControl && !coinControl->m_add_inputs && !coinControl->IsSelected(COutPoint(entry.first, i))) {
#         [ +  + ][ +  + ]
#     163                 :       1820 :                 continue;
#     164                 :       1820 :             }
#     165                 :            : 
#     166 [ +  + ][ -  + ]:    1926513 :             if (wtx.tx->vout[i].nValue < nMinimumAmount || wtx.tx->vout[i].nValue > nMaximumAmount)
#     167                 :     313517 :                 continue;
#     168                 :            : 
#     169 [ +  + ][ -  + ]:    1612996 :             if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(entry.first, i)))
#         [ +  + ][ -  + ]
#                 [ #  # ]
#     170                 :          0 :                 continue;
#     171                 :            : 
#     172         [ +  + ]:    1612996 :             if (wallet.IsLockedCoin(entry.first, i))
#     173                 :        782 :                 continue;
#     174                 :            : 
#     175         [ +  + ]:    1612214 :             if (wallet.IsSpent(wtxid, i))
#     176                 :     860103 :                 continue;
#     177                 :            : 
#     178                 :     752111 :             isminetype mine = wallet.IsMine(wtx.tx->vout[i]);
#     179                 :            : 
#     180         [ +  + ]:     752111 :             if (mine == ISMINE_NO) {
#     181                 :     409177 :                 continue;
#     182                 :     409177 :             }
#     183                 :            : 
#     184 [ +  + ][ +  + ]:     342934 :             if (!allow_used_addresses && wallet.IsSpentKey(wtxid, i)) {
#     185                 :          6 :                 continue;
#     186                 :          6 :             }
#     187                 :            : 
#     188                 :     342928 :             std::unique_ptr<SigningProvider> provider = wallet.GetSolvingProvider(wtx.tx->vout[i].scriptPubKey);
#     189                 :            : 
#     190         [ +  - ]:     342928 :             bool solvable = provider ? IsSolvable(*provider, wtx.tx->vout[i].scriptPubKey) : false;
#     191 [ +  + ][ +  - ]:     342928 :             bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
#         [ +  - ][ +  + ]
#                 [ +  - ]
#     192 [ +  + ][ +  + ]:     342928 :             int input_bytes = GetTxSpendSize(wallet, wtx, i, (coinControl && coinControl->fAllowWatchOnly));
#     193                 :            : 
#     194                 :     342928 :             vCoins.emplace_back(COutPoint(wtx.GetHash(), i), wtx.tx->vout.at(i), nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me);
#     195                 :            : 
#     196                 :            :             // Checks the sum amount of all UTXO's.
#     197         [ -  + ]:     342928 :             if (nMinimumSumAmount != MAX_MONEY) {
#     198                 :          0 :                 nTotal += wtx.tx->vout[i].nValue;
#     199                 :            : 
#     200         [ #  # ]:          0 :                 if (nTotal >= nMinimumSumAmount) {
#     201                 :          0 :                     return;
#     202                 :          0 :                 }
#     203                 :          0 :             }
#     204                 :            : 
#     205                 :            :             // Checks the maximum number of UTXO's.
#     206 [ -  + ][ #  # ]:     342928 :             if (nMaximumCount > 0 && vCoins.size() >= nMaximumCount) {
#     207                 :          0 :                 return;
#     208                 :          0 :             }
#     209                 :     342928 :         }
#     210                 :     883237 :     }
#     211                 :       5986 : }
#     212                 :            : 
#     213                 :            : CAmount GetAvailableBalance(const CWallet& wallet, const CCoinControl* coinControl)
#     214                 :          3 : {
#     215                 :          3 :     LOCK(wallet.cs_wallet);
#     216                 :            : 
#     217                 :          3 :     CAmount balance = 0;
#     218                 :          3 :     std::vector<COutput> vCoins;
#     219                 :          3 :     AvailableCoins(wallet, vCoins, coinControl);
#     220         [ +  + ]:         10 :     for (const COutput& out : vCoins) {
#     221         [ +  - ]:         10 :         if (out.spendable) {
#     222                 :         10 :             balance += out.txout.nValue;
#     223                 :         10 :         }
#     224                 :         10 :     }
#     225                 :          3 :     return balance;
#     226                 :          3 : }
#     227                 :            : 
#     228                 :            : const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const CTransaction& tx, int output)
#     229                 :          5 : {
#     230                 :          5 :     AssertLockHeld(wallet.cs_wallet);
#     231                 :          5 :     const CTransaction* ptx = &tx;
#     232                 :          5 :     int n = output;
#     233 [ +  - ][ +  - ]:          7 :     while (OutputIsChange(wallet, ptx->vout[n]) && ptx->vin.size() > 0) {
#     234                 :          7 :         const COutPoint& prevout = ptx->vin[0].prevout;
#     235                 :          7 :         auto it = wallet.mapWallet.find(prevout.hash);
#     236 [ +  + ][ +  + ]:          7 :         if (it == wallet.mapWallet.end() || it->second.tx->vout.size() <= prevout.n ||
#                 [ -  + ]
#     237         [ -  + ]:          7 :             !wallet.IsMine(it->second.tx->vout[prevout.n])) {
#     238                 :          5 :             break;
#     239                 :          5 :         }
#     240                 :          2 :         ptx = it->second.tx.get();
#     241                 :          2 :         n = prevout.n;
#     242                 :          2 :     }
#     243                 :          5 :     return ptx->vout[n];
#     244                 :          5 : }
#     245                 :            : 
#     246                 :            : const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const COutPoint& outpoint)
#     247                 :          3 : {
#     248                 :          3 :     AssertLockHeld(wallet.cs_wallet);
#     249                 :          3 :     return FindNonChangeParentOutput(wallet, *wallet.GetWalletTx(outpoint.hash)->tx, outpoint.n);
#     250                 :          3 : }
#     251                 :            : 
#     252                 :            : std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet)
#     253                 :          3 : {
#     254                 :          3 :     AssertLockHeld(wallet.cs_wallet);
#     255                 :            : 
#     256                 :          3 :     std::map<CTxDestination, std::vector<COutput>> result;
#     257                 :          3 :     std::vector<COutput> availableCoins;
#     258                 :            : 
#     259                 :          3 :     AvailableCoins(wallet, availableCoins);
#     260                 :            : 
#     261         [ +  + ]:          3 :     for (const COutput& coin : availableCoins) {
#     262                 :          3 :         CTxDestination address;
#     263 [ +  - ][ #  # ]:          3 :         if ((coin.spendable || (wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && coin.solvable)) &&
#                 [ #  # ]
#     264         [ +  - ]:          3 :             ExtractDestination(FindNonChangeParentOutput(wallet, coin.outpoint).scriptPubKey, address)) {
#     265                 :          3 :             result[address].emplace_back(std::move(coin));
#     266                 :          3 :         }
#     267                 :          3 :     }
#     268                 :            : 
#     269                 :          3 :     std::vector<COutPoint> lockedCoins;
#     270                 :          3 :     wallet.ListLockedCoins(lockedCoins);
#     271                 :            :     // Include watch-only for LegacyScriptPubKeyMan wallets without private keys
#     272 [ -  + ][ #  # ]:          3 :     const bool include_watch_only = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
#     273         [ -  + ]:          3 :     const isminetype is_mine_filter = include_watch_only ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
#     274         [ +  + ]:          3 :     for (const COutPoint& output : lockedCoins) {
#     275                 :          2 :         auto it = wallet.mapWallet.find(output.hash);
#     276         [ +  - ]:          2 :         if (it != wallet.mapWallet.end()) {
#     277                 :          2 :             const auto& wtx = it->second;
#     278                 :          2 :             int depth = wallet.GetTxDepthInMainChain(wtx);
#     279 [ +  - ][ +  - ]:          2 :             if (depth >= 0 && output.n < wtx.tx->vout.size() &&
#     280         [ +  - ]:          2 :                 wallet.IsMine(wtx.tx->vout[output.n]) == is_mine_filter
#     281                 :          2 :             ) {
#     282                 :          2 :                 CTxDestination address;
#     283         [ +  - ]:          2 :                 if (ExtractDestination(FindNonChangeParentOutput(wallet, *wtx.tx, output.n).scriptPubKey, address)) {
#     284                 :          2 :                     result[address].emplace_back(
#     285                 :          2 :                         COutPoint(wtx.GetHash(), output.n), wtx.tx->vout.at(output.n), depth, GetTxSpendSize(wallet, wtx, output.n), /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ false, wtx.GetTxTime(), CachedTxIsFromMe(wallet, wtx, ISMINE_ALL));
#     286                 :          2 :                 }
#     287                 :          2 :             }
#     288                 :          2 :         }
#     289                 :          2 :     }
#     290                 :            : 
#     291                 :          3 :     return result;
#     292                 :          3 : }
#     293                 :            : 
#     294                 :            : std::vector<OutputGroup> GroupOutputs(const CWallet& wallet, const std::vector<COutput>& outputs, const CoinSelectionParams& coin_sel_params, const CoinEligibilityFilter& filter, bool positive_only)
#     295                 :      19149 : {
#     296                 :      19149 :     std::vector<OutputGroup> groups_out;
#     297                 :            : 
#     298         [ +  + ]:      19149 :     if (!coin_sel_params.m_avoid_partial_spends) {
#     299                 :            :         // Allowing partial spends  means no grouping. Each COutput gets its own OutputGroup.
#     300         [ +  + ]:     936105 :         for (const COutput& output : outputs) {
#     301                 :            :             // Skip outputs we cannot spend
#     302         [ +  + ]:     936105 :             if (!output.spendable) continue;
#     303                 :            : 
#     304                 :     935915 :             size_t ancestors, descendants;
#     305                 :     935915 :             wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, descendants);
#     306                 :            : 
#     307                 :            :             // Make an OutputGroup containing just this output
#     308                 :     935915 :             OutputGroup group{coin_sel_params};
#     309                 :     935915 :             group.Insert(output, ancestors, descendants, positive_only);
#     310                 :            : 
#     311                 :            :             // Check the OutputGroup's eligibility. Only add the eligible ones.
#     312 [ +  + ][ +  + ]:     935915 :             if (positive_only && group.GetSelectionAmount() <= 0) continue;
#     313 [ +  - ][ +  + ]:     935899 :             if (group.m_outputs.size() > 0 && group.EligibleForSpending(filter)) groups_out.push_back(group);
#     314                 :     935899 :         }
#     315                 :      11537 :         return groups_out;
#     316                 :      11537 :     }
#     317                 :            : 
#     318                 :            :     // We want to combine COutputs that have the same scriptPubKey into single OutputGroups
#     319                 :            :     // except when there are more than OUTPUT_GROUP_MAX_ENTRIES COutputs grouped in an OutputGroup.
#     320                 :            :     // To do this, we maintain a map where the key is the scriptPubKey and the value is a vector of OutputGroups.
#     321                 :            :     // For each COutput, we check if the scriptPubKey is in the map, and if it is, the COutput is added
#     322                 :            :     // to the last OutputGroup in the vector for the scriptPubKey. When the last OutputGroup has
#     323                 :            :     // OUTPUT_GROUP_MAX_ENTRIES COutputs, a new OutputGroup is added to the end of the vector.
#     324                 :       7612 :     std::map<CScript, std::vector<OutputGroup>> spk_to_groups_map;
#     325         [ +  + ]:     458342 :     for (const auto& output : outputs) {
#     326                 :            :         // Skip outputs we cannot spend
#     327         [ +  + ]:     458342 :         if (!output.spendable) continue;
#     328                 :            : 
#     329                 :     458212 :         size_t ancestors, descendants;
#     330                 :     458212 :         wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, descendants);
#     331                 :     458212 :         CScript spk = output.txout.scriptPubKey;
#     332                 :            : 
#     333                 :     458212 :         std::vector<OutputGroup>& groups = spk_to_groups_map[spk];
#     334                 :            : 
#     335         [ +  + ]:     458212 :         if (groups.size() == 0) {
#     336                 :            :             // No OutputGroups for this scriptPubKey yet, add one
#     337                 :     255554 :             groups.emplace_back(coin_sel_params);
#     338                 :     255554 :         }
#     339                 :            : 
#     340                 :            :         // Get the last OutputGroup in the vector so that we can add the COutput to it
#     341                 :            :         // A pointer is used here so that group can be reassigned later if it is full.
#     342                 :     458212 :         OutputGroup* group = &groups.back();
#     343                 :            : 
#     344                 :            :         // Check if this OutputGroup is full. We limit to OUTPUT_GROUP_MAX_ENTRIES when using -avoidpartialspends
#     345                 :            :         // to avoid surprising users with very high fees.
#     346         [ +  + ]:     458212 :         if (group->m_outputs.size() >= OUTPUT_GROUP_MAX_ENTRIES) {
#     347                 :            :             // The last output group is full, add a new group to the vector and use that group for the insertion
#     348                 :       1366 :             groups.emplace_back(coin_sel_params);
#     349                 :       1366 :             group = &groups.back();
#     350                 :       1366 :         }
#     351                 :            : 
#     352                 :            :         // Add the output to group
#     353                 :     458212 :         group->Insert(output, ancestors, descendants, positive_only);
#     354                 :     458212 :     }
#     355                 :            : 
#     356                 :            :     // Now we go through the entire map and pull out the OutputGroups
#     357         [ +  + ]:     255554 :     for (const auto& spk_and_groups_pair: spk_to_groups_map) {
#     358                 :     255554 :         const std::vector<OutputGroup>& groups_per_spk= spk_and_groups_pair.second;
#     359                 :            : 
#     360                 :            :         // Go through the vector backwards. This allows for the first item we deal with being the partial group.
#     361         [ +  + ]:     512474 :         for (auto group_it = groups_per_spk.rbegin(); group_it != groups_per_spk.rend(); group_it++) {
#     362                 :     256920 :             const OutputGroup& group = *group_it;
#     363                 :            : 
#     364                 :            :             // Don't include partial groups if there are full groups too and we don't want partial groups
#     365 [ +  + ][ +  + ]:     256920 :             if (group_it == groups_per_spk.rbegin() && groups_per_spk.size() > 1 && !filter.m_include_partial_groups) {
#         [ +  + ][ +  + ]
#     366                 :        410 :                 continue;
#     367                 :        410 :             }
#     368                 :            : 
#     369                 :            :             // Check the OutputGroup's eligibility. Only add the eligible ones.
#     370 [ +  + ][ +  + ]:     256510 :             if (positive_only && group.GetSelectionAmount() <= 0) continue;
#     371 [ +  - ][ +  + ]:     256504 :             if (group.m_outputs.size() > 0 && group.EligibleForSpending(filter)) groups_out.push_back(group);
#     372                 :     256504 :         }
#     373                 :     255554 :     }
#     374                 :            : 
#     375                 :       7612 :     return groups_out;
#     376                 :      19149 : }
#     377                 :            : 
#     378                 :            : std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutput> coins,
#     379                 :            :                                const CoinSelectionParams& coin_selection_params)
#     380                 :       7874 : {
#     381                 :            :     // Vector of results. We will choose the best one based on waste.
#     382                 :       7874 :     std::vector<SelectionResult> results;
#     383                 :            : 
#     384                 :            :     // Note that unlike KnapsackSolver, we do not include the fee for creating a change output as BnB will not create a change output.
#     385                 :       7874 :     std::vector<OutputGroup> positive_groups = GroupOutputs(wallet, coins, coin_selection_params, eligibility_filter, true /* positive_only */);
#     386         [ +  + ]:       7874 :     if (auto bnb_result{SelectCoinsBnB(positive_groups, nTargetValue, coin_selection_params.m_cost_of_change)}) {
#     387                 :        217 :         results.push_back(*bnb_result);
#     388                 :        217 :     }
#     389                 :            : 
#     390                 :            :     // The knapsack solver has some legacy behavior where it will spend dust outputs. We retain this behavior, so don't filter for positive only here.
#     391                 :       7874 :     std::vector<OutputGroup> all_groups = GroupOutputs(wallet, coins, coin_selection_params, eligibility_filter, false /* positive_only */);
#     392                 :            :     // While nTargetValue includes the transaction fees for non-input things, it does not include the fee for creating a change output.
#     393                 :            :     // So we need to include that for KnapsackSolver as well, as we are expecting to create a change output.
#     394         [ +  + ]:       7874 :     if (auto knapsack_result{KnapsackSolver(all_groups, nTargetValue + coin_selection_params.m_change_fee,
#     395                 :       7874 :                                             coin_selection_params.m_min_change_target, coin_selection_params.rng_fast)}) {
#     396                 :       4907 :         knapsack_result->ComputeAndSetWaste(coin_selection_params.m_cost_of_change);
#     397                 :       4907 :         results.push_back(*knapsack_result);
#     398                 :       4907 :     }
#     399                 :            : 
#     400                 :            :     // Include change for SRD as we want to avoid making really small change if the selection just
#     401                 :            :     // barely meets the target. Just use the lower bound change target instead of the randomly
#     402                 :            :     // generated one, since SRD will result in a random change amount anyway; avoid making the
#     403                 :            :     // target needlessly large.
#     404                 :       7874 :     const CAmount srd_target = nTargetValue + coin_selection_params.m_change_fee + CHANGE_LOWER;
#     405         [ +  + ]:       7874 :     if (auto srd_result{SelectCoinsSRD(positive_groups, srd_target, coin_selection_params.rng_fast)}) {
#     406                 :       4892 :         srd_result->ComputeAndSetWaste(coin_selection_params.m_cost_of_change);
#     407                 :       4892 :         results.push_back(*srd_result);
#     408                 :       4892 :     }
#     409                 :            : 
#     410         [ +  + ]:       7874 :     if (results.size() == 0) {
#     411                 :            :         // No solution found
#     412                 :       2873 :         return std::nullopt;
#     413                 :       2873 :     }
#     414                 :            : 
#     415                 :            :     // Choose the result with the least waste
#     416                 :            :     // If the waste is the same, choose the one which spends more inputs.
#     417                 :       5001 :     auto& best_result = *std::min_element(results.begin(), results.end());
#     418                 :       5001 :     return best_result;
#     419                 :       7874 : }
#     420                 :            : 
#     421                 :            : std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
#     422                 :       5493 : {
#     423                 :       5493 :     std::vector<COutput> vCoins(vAvailableCoins);
#     424                 :       5493 :     CAmount value_to_select = nTargetValue;
#     425                 :            : 
#     426                 :       5493 :     OutputGroup preset_inputs(coin_selection_params);
#     427                 :            : 
#     428                 :            :     // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
#     429 [ +  + ][ -  + ]:       5493 :     if (coin_control.HasSelected() && !coin_control.fAllowOtherInputs)
#     430                 :          0 :     {
#     431         [ #  # ]:          0 :         for (const COutput& out : vCoins) {
#     432         [ #  # ]:          0 :             if (!out.spendable) continue;
#     433                 :            :             /* Set ancestors and descendants to 0 as these don't matter for preset inputs as no actual selection is being done.
#     434                 :            :              * positive_only is set to false because we want to include all preset inputs, even if they are dust.
#     435                 :            :              */
#     436                 :          0 :             preset_inputs.Insert(out, /*ancestors=*/ 0, /*descendants=*/ 0, /*positive_only=*/ false);
#     437                 :          0 :         }
#     438                 :          0 :         SelectionResult result(nTargetValue);
#     439                 :          0 :         result.AddInput(preset_inputs);
#     440         [ #  # ]:          0 :         if (result.GetSelectedValue() < nTargetValue) return std::nullopt;
#     441                 :          0 :         return result;
#     442                 :          0 :     }
#     443                 :            : 
#     444                 :            :     // calculate value from preset inputs and store them
#     445                 :       5493 :     std::set<COutPoint> preset_coins;
#     446                 :            : 
#     447                 :       5493 :     std::vector<COutPoint> vPresetInputs;
#     448                 :       5493 :     coin_control.ListSelected(vPresetInputs);
#     449         [ +  + ]:       5493 :     for (const COutPoint& outpoint : vPresetInputs) {
#     450                 :       1001 :         int input_bytes = -1;
#     451                 :       1001 :         CTxOut txout;
#     452                 :       1001 :         std::map<uint256, CWalletTx>::const_iterator it = wallet.mapWallet.find(outpoint.hash);
#     453         [ +  + ]:       1001 :         if (it != wallet.mapWallet.end()) {
#     454                 :        921 :             const CWalletTx& wtx = it->second;
#     455                 :            :             // Clearly invalid input, fail
#     456         [ -  + ]:        921 :             if (wtx.tx->vout.size() <= outpoint.n) {
#     457                 :          0 :                 return std::nullopt;
#     458                 :          0 :             }
#     459                 :        921 :             input_bytes = GetTxSpendSize(wallet, wtx, outpoint.n, false);
#     460                 :        921 :             txout = wtx.tx->vout.at(outpoint.n);
#     461                 :        921 :         } else {
#     462                 :            :             // The input is external. We did not find the tx in mapWallet.
#     463         [ +  + ]:         80 :             if (!coin_control.GetExternalOutput(outpoint, txout)) {
#     464                 :          2 :                 return std::nullopt;
#     465                 :          2 :             }
#     466                 :         78 :             input_bytes = CalculateMaximumSignedInputSize(txout, &coin_control.m_external_provider, /*use_max_sig=*/true);
#     467                 :         78 :         }
#     468                 :            :         // If available, override calculated size with coin control specified size
#     469         [ +  + ]:        999 :         if (coin_control.HasInputWeight(outpoint)) {
#     470                 :         52 :             input_bytes = GetVirtualTransactionSize(coin_control.GetInputWeight(outpoint), 0, 0);
#     471                 :         52 :         }
#     472                 :            : 
#     473         [ +  + ]:        999 :         if (input_bytes == -1) {
#     474                 :          6 :             return std::nullopt; // Not solvable, can't estimate size for fee
#     475                 :          6 :         }
#     476                 :            : 
#     477                 :            :         /* Set some defaults for depth, spendable, solvable, safe, time, and from_me as these don't matter for preset inputs since no selection is being done. */
#     478                 :        993 :         COutput output(outpoint, txout, /*depth=*/ 0, input_bytes, /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ true, /*time=*/ 0, /*from_me=*/ false);
#     479                 :        993 :         output.effective_value = output.txout.nValue - coin_selection_params.m_effective_feerate.GetFee(output.input_bytes);
#     480         [ +  + ]:        993 :         if (coin_selection_params.m_subtract_fee_outputs) {
#     481                 :          9 :             value_to_select -= output.txout.nValue;
#     482                 :        984 :         } else {
#     483                 :        984 :             value_to_select -= output.effective_value;
#     484                 :        984 :         }
#     485                 :        993 :         preset_coins.insert(outpoint);
#     486                 :            :         /* Set ancestors and descendants to 0 as they don't matter for preset inputs since no actual selection is being done.
#     487                 :            :          * positive_only is set to false because we want to include all preset inputs, even if they are dust.
#     488                 :            :          */
#     489                 :        993 :         preset_inputs.Insert(output, /*ancestors=*/ 0, /*descendants=*/ 0, /*positive_only=*/ false);
#     490                 :        993 :     }
#     491                 :            : 
#     492                 :            :     // remove preset inputs from vCoins so that Coin Selection doesn't pick them.
#     493 [ +  + ][ +  + ]:      41908 :     for (std::vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coin_control.HasSelected();)
#                 [ +  + ]
#     494                 :      36423 :     {
#     495         [ +  + ]:      36423 :         if (preset_coins.count(it->outpoint))
#     496                 :        153 :             it = vCoins.erase(it);
#     497                 :      36270 :         else
#     498                 :      36270 :             ++it;
#     499                 :      36423 :     }
#     500                 :            : 
#     501                 :       5485 :     unsigned int limit_ancestor_count = 0;
#     502                 :       5485 :     unsigned int limit_descendant_count = 0;
#     503                 :       5485 :     wallet.chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
#     504                 :       5485 :     const size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
#     505                 :       5485 :     const size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
#     506                 :       5485 :     const bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS);
#     507                 :            : 
#     508                 :            :     // form groups from remaining coins; note that preset coins will not
#     509                 :            :     // automatically have their associated (same address) coins included
#     510 [ +  + ][ +  + ]:       5485 :     if (coin_control.m_avoid_partial_spends && vCoins.size() > OUTPUT_GROUP_MAX_ENTRIES) {
#     511                 :            :         // Cases where we have 101+ outputs all pointing to the same destination may result in
#     512                 :            :         // privacy leaks as they will potentially be deterministically sorted. We solve that by
#     513                 :            :         // explicitly shuffling the outputs before processing
#     514                 :        315 :         Shuffle(vCoins.begin(), vCoins.end(), coin_selection_params.rng_fast);
#     515                 :        315 :     }
#     516                 :            : 
#     517                 :            :     // Coin Selection attempts to select inputs from a pool of eligible UTXOs to fund the
#     518                 :            :     // transaction at a target feerate. If an attempt fails, more attempts may be made using a more
#     519                 :            :     // permissive CoinEligibilityFilter.
#     520                 :       5485 :     std::optional<SelectionResult> res = [&] {
#     521                 :            :         // Pre-selected inputs already cover the target amount.
#     522         [ +  + ]:       5485 :         if (value_to_select <= 0) return std::make_optional(SelectionResult(nTargetValue));
#     523                 :            : 
#     524                 :            :         // If possible, fund the transaction with confirmed UTXOs only. Prefer at least six
#     525                 :            :         // confirmations on outputs received from other wallets and only spend confirmed change.
#     526         [ +  + ]:       5033 :         if (auto r1{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 6, 0), vCoins, coin_selection_params)}) return r1;
#     527         [ +  + ]:       1551 :         if (auto r2{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 1, 0), vCoins, coin_selection_params)}) return r2;
#     528                 :            : 
#     529                 :            :         // Fall back to using zero confirmation change (but with as few ancestors in the mempool as
#     530                 :            :         // possible) if we cannot fund the transaction otherwise.
#     531         [ +  - ]:        962 :         if (wallet.m_spend_zero_conf_change) {
#     532         [ +  + ]:        962 :             if (auto r3{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, 2), vCoins, coin_selection_params)}) return r3;
#     533         [ +  + ]:        128 :             if (auto r4{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)),
#     534                 :        128 :                                    vCoins, coin_selection_params)}) {
#     535                 :         20 :                 return r4;
#     536                 :         20 :             }
#     537         [ +  + ]:        108 :             if (auto r5{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2),
#     538                 :        108 :                                    vCoins, coin_selection_params)}) {
#     539                 :         38 :                 return r5;
#     540                 :         38 :             }
#     541                 :            :             // If partial groups are allowed, relax the requirement of spending OutputGroups (groups
#     542                 :            :             // of UTXOs sent to the same address, which are obviously controlled by a single wallet)
#     543                 :            :             // in their entirety.
#     544         [ +  + ]:         70 :             if (auto r6{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
#     545                 :         70 :                                    vCoins, coin_selection_params)}) {
#     546                 :         18 :                 return r6;
#     547                 :         18 :             }
#     548                 :            :             // Try with unsafe inputs if they are allowed. This may spend unconfirmed outputs
#     549                 :            :             // received from other wallets.
#     550         [ +  + ]:         52 :             if (coin_control.m_include_unsafe_inputs) {
#     551         [ +  - ]:         12 :                 if (auto r7{AttemptSelection(wallet, value_to_select,
#     552                 :         12 :                     CoinEligibilityFilter(0 /* conf_mine */, 0 /* conf_theirs */, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
#     553                 :         12 :                     vCoins, coin_selection_params)}) {
#     554                 :         12 :                     return r7;
#     555                 :         12 :                 }
#     556                 :         12 :             }
#     557                 :            :             // Try with unlimited ancestors/descendants. The transaction will still need to meet
#     558                 :            :             // mempool ancestor/descendant policy to be accepted to mempool and broadcasted, but
#     559                 :            :             // OutputGroups use heuristics that may overestimate ancestor/descendant counts.
#     560         [ +  + ]:         40 :             if (!fRejectLongChains) {
#     561         [ +  + ]:         10 :                 if (auto r8{AttemptSelection(wallet, value_to_select,
#     562                 :         10 :                                       CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), true /* include_partial_groups */),
#     563                 :         10 :                                       vCoins, coin_selection_params)}) {
#     564                 :          8 :                     return r8;
#     565                 :          8 :                 }
#     566                 :         10 :             }
#     567                 :         40 :         }
#     568                 :            :         // Coin Selection failed.
#     569                 :         32 :         return std::optional<SelectionResult>();
#     570                 :        962 :     }();
#     571                 :            : 
#     572         [ +  + ]:       5485 :     if (!res) return std::nullopt;
#     573                 :            : 
#     574                 :            :     // Add preset inputs to result
#     575                 :       5453 :     res->AddInput(preset_inputs);
#     576                 :            : 
#     577                 :       5453 :     return res;
#     578                 :       5485 : }
#     579                 :            : 
#     580                 :            : static bool IsCurrentForAntiFeeSniping(interfaces::Chain& chain, const uint256& block_hash)
#     581                 :       5352 : {
#     582         [ +  + ]:       5352 :     if (chain.isInitialBlockDownload()) {
#     583                 :          2 :         return false;
#     584                 :          2 :     }
#     585                 :       5350 :     constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60; // in seconds
#     586                 :       5350 :     int64_t block_time;
#     587         [ -  + ]:       5350 :     CHECK_NONFATAL(chain.findBlock(block_hash, FoundBlock().time(block_time)));
#     588         [ +  + ]:       5350 :     if (block_time < (GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
#     589                 :         16 :         return false;
#     590                 :         16 :     }
#     591                 :       5334 :     return true;
#     592                 :       5350 : }
#     593                 :            : 
#     594                 :            : /**
#     595                 :            :  * Set a height-based locktime for new transactions (uses the height of the
#     596                 :            :  * current chain tip unless we are not synced with the current chain
#     597                 :            :  */
#     598                 :            : static void DiscourageFeeSniping(CMutableTransaction& tx, FastRandomContext& rng_fast,
#     599                 :            :                                  interfaces::Chain& chain, const uint256& block_hash, int block_height)
#     600                 :       5352 : {
#     601                 :            :     // All inputs must be added by now
#     602                 :       5352 :     assert(!tx.vin.empty());
#     603                 :            :     // Discourage fee sniping.
#     604                 :            :     //
#     605                 :            :     // For a large miner the value of the transactions in the best block and
#     606                 :            :     // the mempool can exceed the cost of deliberately attempting to mine two
#     607                 :            :     // blocks to orphan the current best block. By setting nLockTime such that
#     608                 :            :     // only the next block can include the transaction, we discourage this
#     609                 :            :     // practice as the height restricted and limited blocksize gives miners
#     610                 :            :     // considering fee sniping fewer options for pulling off this attack.
#     611                 :            :     //
#     612                 :            :     // A simple way to think about this is from the wallet's point of view we
#     613                 :            :     // always want the blockchain to move forward. By setting nLockTime this
#     614                 :            :     // way we're basically making the statement that we only want this
#     615                 :            :     // transaction to appear in the next block; we don't want to potentially
#     616                 :            :     // encourage reorgs by allowing transactions to appear at lower heights
#     617                 :            :     // than the next block in forks of the best chain.
#     618                 :            :     //
#     619                 :            :     // Of course, the subsidy is high enough, and transaction volume low
#     620                 :            :     // enough, that fee sniping isn't a problem yet, but by implementing a fix
#     621                 :            :     // now we ensure code won't be written that makes assumptions about
#     622                 :            :     // nLockTime that preclude a fix later.
#     623         [ +  + ]:       5352 :     if (IsCurrentForAntiFeeSniping(chain, block_hash)) {
#     624                 :       5334 :         tx.nLockTime = block_height;
#     625                 :            : 
#     626                 :            :         // Secondly occasionally randomly pick a nLockTime even further back, so
#     627                 :            :         // that transactions that are delayed after signing for whatever reason,
#     628                 :            :         // e.g. high-latency mix networks and some CoinJoin implementations, have
#     629                 :            :         // better privacy.
#     630         [ +  + ]:       5334 :         if (rng_fast.randrange(10) == 0) {
#     631                 :        569 :             tx.nLockTime = std::max(0, int(tx.nLockTime) - int(rng_fast.randrange(100)));
#     632                 :        569 :         }
#     633                 :       5334 :     } else {
#     634                 :            :         // If our chain is lagging behind, we can't discourage fee sniping nor help
#     635                 :            :         // the privacy of high-latency transactions. To avoid leaking a potentially
#     636                 :            :         // unique "nLockTime fingerprint", set nLockTime to a constant.
#     637                 :         18 :         tx.nLockTime = 0;
#     638                 :         18 :     }
#     639                 :            :     // Sanity check all values
#     640                 :       5352 :     assert(tx.nLockTime < LOCKTIME_THRESHOLD); // Type must be block height
#     641                 :          0 :     assert(tx.nLockTime <= uint64_t(block_height));
#     642         [ +  + ]:      22608 :     for (const auto& in : tx.vin) {
#     643                 :            :         // Can not be FINAL for locktime to work
#     644                 :      22608 :         assert(in.nSequence != CTxIn::SEQUENCE_FINAL);
#     645                 :            :         // May be MAX NONFINAL to disable both BIP68 and BIP125
#     646         [ +  + ]:      22608 :         if (in.nSequence == CTxIn::MAX_SEQUENCE_NONFINAL) continue;
#     647                 :            :         // May be MAX BIP125 to disable BIP68 and enable BIP125
#     648         [ +  - ]:       3210 :         if (in.nSequence == MAX_BIP125_RBF_SEQUENCE) continue;
#     649                 :            :         // The wallet does not support any other sequence-use right now.
#     650                 :          0 :         assert(false);
#     651                 :          0 :     }
#     652                 :       5352 : }
#     653                 :            : 
#     654                 :            : static bool CreateTransactionInternal(
#     655                 :            :         CWallet& wallet,
#     656                 :            :         const std::vector<CRecipient>& vecSend,
#     657                 :            :         CTransactionRef& tx,
#     658                 :            :         CAmount& nFeeRet,
#     659                 :            :         int& nChangePosInOut,
#     660                 :            :         bilingual_str& error,
#     661                 :            :         const CCoinControl& coin_control,
#     662                 :            :         FeeCalculation& fee_calc_out,
#     663                 :            :         bool sign) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
#     664                 :       5447 : {
#     665                 :       5447 :     AssertLockHeld(wallet.cs_wallet);
#     666                 :            : 
#     667                 :       5447 :     FastRandomContext rng_fast;
#     668                 :       5447 :     CMutableTransaction txNew; // The resulting transaction that we make
#     669                 :            : 
#     670                 :       5447 :     CoinSelectionParams coin_selection_params{rng_fast}; // Parameters for coin selection, init with dummy
#     671                 :       5447 :     coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends;
#     672                 :            : 
#     673                 :            :     // Set the long term feerate estimate to the wallet's consolidate feerate
#     674                 :       5447 :     coin_selection_params.m_long_term_feerate = wallet.m_consolidate_feerate;
#     675                 :            : 
#     676                 :       5447 :     CAmount recipients_sum = 0;
#     677         [ +  + ]:       5447 :     const OutputType change_type = wallet.TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : wallet.m_default_change_type, vecSend);
#     678                 :       5447 :     ReserveDestination reservedest(&wallet, change_type);
#     679                 :       5447 :     unsigned int outputs_to_subtract_fee_from = 0; // The number of outputs which we are subtracting the fee from
#     680         [ +  + ]:      58357 :     for (const auto& recipient : vecSend) {
#     681                 :      58357 :         recipients_sum += recipient.nAmount;
#     682                 :            : 
#     683         [ +  + ]:      58357 :         if (recipient.fSubtractFeeFromAmount) {
#     684                 :        658 :             outputs_to_subtract_fee_from++;
#     685                 :        658 :             coin_selection_params.m_subtract_fee_outputs = true;
#     686                 :        658 :         }
#     687                 :      58357 :     }
#     688                 :       5447 :     coin_selection_params.m_change_target = GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), rng_fast);
#     689                 :            : 
#     690                 :            :     // Create change script that will be used if we need change
#     691                 :       5447 :     CScript scriptChange;
#     692                 :            : 
#     693                 :            :     // coin control: send change to custom address
#     694         [ +  + ]:       5447 :     if (!std::get_if<CNoDestination>(&coin_control.destChange)) {
#     695                 :        338 :         scriptChange = GetScriptForDestination(coin_control.destChange);
#     696                 :       5109 :     } else { // no coin control: send change to newly generated address
#     697                 :            :         // Note: We use a new key here to keep it from being obvious which side is the change.
#     698                 :            :         //  The drawback is that by not reusing a previous key, the change may be lost if a
#     699                 :            :         //  backup is restored, if the backup doesn't have the new private key for the change.
#     700                 :            :         //  If we reused the old key, it would be possible to add code to look for and
#     701                 :            :         //  rediscover unknown transactions that were written with keys of ours to recover
#     702                 :            :         //  post-backup change.
#     703                 :            : 
#     704                 :            :         // Reserve a new key pair from key pool. If it fails, provide a dummy
#     705                 :            :         // destination in case we don't need change.
#     706                 :       5109 :         CTxDestination dest;
#     707                 :       5109 :         bilingual_str dest_err;
#     708         [ +  + ]:       5109 :         if (!reservedest.GetReservedDestination(dest, true, dest_err)) {
#     709                 :         29 :             error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + dest_err;
#     710                 :         29 :         }
#     711                 :       5109 :         scriptChange = GetScriptForDestination(dest);
#     712                 :            :         // A valid destination implies a change script (and
#     713                 :            :         // vice-versa). An empty change script will abort later, if the
#     714                 :            :         // change keypool ran out, but change is required.
#     715         [ -  + ]:       5109 :         CHECK_NONFATAL(IsValidDestination(dest) != scriptChange.empty());
#     716                 :       5109 :     }
#     717                 :       5447 :     CTxOut change_prototype_txout(0, scriptChange);
#     718                 :       5447 :     coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout);
#     719                 :            : 
#     720                 :            :     // Get size of spending the change output
#     721                 :       5447 :     int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, &wallet);
#     722                 :            :     // If the wallet doesn't know how to sign change output, assume p2sh-p2wpkh
#     723                 :            :     // as lower-bound to allow BnB to do it's thing
#     724         [ +  + ]:       5447 :     if (change_spend_size == -1) {
#     725                 :         49 :         coin_selection_params.change_spend_size = DUMMY_NESTED_P2WPKH_INPUT_SIZE;
#     726                 :       5398 :     } else {
#     727                 :       5398 :         coin_selection_params.change_spend_size = (size_t)change_spend_size;
#     728                 :       5398 :     }
#     729                 :            : 
#     730                 :            :     // Set discard feerate
#     731                 :       5447 :     coin_selection_params.m_discard_feerate = GetDiscardRate(wallet);
#     732                 :            : 
#     733                 :            :     // Get the fee rate to use effective values in coin selection
#     734                 :       5447 :     FeeCalculation feeCalc;
#     735                 :       5447 :     coin_selection_params.m_effective_feerate = GetMinimumFeeRate(wallet, coin_control, &feeCalc);
#     736                 :            :     // Do not, ever, assume that it's fine to change the fee rate if the user has explicitly
#     737                 :            :     // provided one
#     738 [ +  + ][ +  + ]:       5447 :     if (coin_control.m_feerate && coin_selection_params.m_effective_feerate > *coin_control.m_feerate) {
#     739                 :         49 :         error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), coin_selection_params.m_effective_feerate.ToString(FeeEstimateMode::SAT_VB));
#     740                 :         49 :         return false;
#     741                 :         49 :     }
#     742 [ +  + ][ +  + ]:       5398 :     if (feeCalc.reason == FeeReason::FALLBACK && !wallet.m_allow_fallback_fee) {
#     743                 :            :         // eventually allow a fallback fee
#     744                 :          6 :         error = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
#     745                 :          6 :         return false;
#     746                 :          6 :     }
#     747                 :            : 
#     748                 :            :     // Calculate the cost of change
#     749                 :            :     // Cost of change is the cost of creating the change output + cost of spending the change output in the future.
#     750                 :            :     // For creating the change output now, we use the effective feerate.
#     751                 :            :     // For spending the change output in the future, we use the discard feerate for now.
#     752                 :            :     // So cost of change = (change output size * effective feerate) + (size of spending change output * discard feerate)
#     753                 :       5392 :     coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);
#     754                 :       5392 :     coin_selection_params.m_cost_of_change = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size) + coin_selection_params.m_change_fee;
#     755                 :            : 
#     756                 :            :     // vouts to the payees
#     757         [ +  + ]:       5392 :     if (!coin_selection_params.m_subtract_fee_outputs) {
#     758                 :       4742 :         coin_selection_params.tx_noinputs_size = 11; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 output count, 1 witness overhead (dummy, flag, stack size)
#     759                 :       4742 :     }
#     760         [ +  + ]:       5392 :     for (const auto& recipient : vecSend)
#     761                 :      58302 :     {
#     762                 :      58302 :         CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
#     763                 :            : 
#     764                 :            :         // Include the fee cost for outputs.
#     765         [ +  + ]:      58302 :         if (!coin_selection_params.m_subtract_fee_outputs) {
#     766                 :      57640 :             coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, PROTOCOL_VERSION);
#     767                 :      57640 :         }
#     768                 :            : 
#     769         [ -  + ]:      58302 :         if (IsDust(txout, wallet.chain().relayDustFee()))
#     770                 :          0 :         {
#     771                 :          0 :             error = _("Transaction amount too small");
#     772                 :          0 :             return false;
#     773                 :          0 :         }
#     774                 :      58302 :         txNew.vout.push_back(txout);
#     775                 :      58302 :     }
#     776                 :            : 
#     777                 :            :     // Include the fees for things that aren't inputs, excluding the change output
#     778                 :       5392 :     const CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.tx_noinputs_size);
#     779                 :       5392 :     CAmount selection_target = recipients_sum + not_input_fees;
#     780                 :            : 
#     781                 :            :     // Get available coins
#     782                 :       5392 :     std::vector<COutput> vAvailableCoins;
#     783                 :       5392 :     AvailableCoins(wallet, vAvailableCoins, &coin_control, 1, MAX_MONEY, MAX_MONEY, 0);
#     784                 :            : 
#     785                 :            :     // Choose coins to use
#     786                 :       5392 :     std::optional<SelectionResult> result = SelectCoins(wallet, vAvailableCoins, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);
#     787         [ +  + ]:       5392 :     if (!result) {
#     788                 :         40 :         error = _("Insufficient funds");
#     789                 :         40 :         return false;
#     790                 :         40 :     }
#     791                 :            : 
#     792                 :            :     // Always make a change output
#     793                 :            :     // We will reduce the fee from this change output later, and remove the output if it is too small.
#     794                 :       5352 :     const CAmount change_and_fee = result->GetSelectedValue() - recipients_sum;
#     795                 :       5352 :     assert(change_and_fee >= 0);
#     796                 :          0 :     CTxOut newTxOut(change_and_fee, scriptChange);
#     797                 :            : 
#     798         [ +  + ]:       5352 :     if (nChangePosInOut == -1) {
#     799                 :            :         // Insert change txn at random position:
#     800                 :       5332 :         nChangePosInOut = rng_fast.randrange(txNew.vout.size() + 1);
#     801                 :       5332 :     }
#     802         [ -  + ]:         20 :     else if ((unsigned int)nChangePosInOut > txNew.vout.size())
#     803                 :          0 :     {
#     804                 :          0 :         error = _("Transaction change output index out of range");
#     805                 :          0 :         return false;
#     806                 :          0 :     }
#     807                 :            : 
#     808                 :       5352 :     assert(nChangePosInOut != -1);
#     809                 :          0 :     auto change_position = txNew.vout.insert(txNew.vout.begin() + nChangePosInOut, newTxOut);
#     810                 :            : 
#     811                 :            :     // Shuffle selected coins and fill in final vin
#     812                 :       5352 :     std::vector<COutput> selected_coins = result->GetShuffledInputVector();
#     813                 :            : 
#     814                 :            :     // The sequence number is set to non-maxint so that DiscourageFeeSniping
#     815                 :            :     // works.
#     816                 :            :     //
#     817                 :            :     // BIP125 defines opt-in RBF as any nSequence < maxint-1, so
#     818                 :            :     // we use the highest possible value in that range (maxint-2)
#     819                 :            :     // to avoid conflicting with other possible uses of nSequence,
#     820                 :            :     // and in the spirit of "smallest possible change from prior
#     821                 :            :     // behavior."
#     822         [ +  + ]:       5352 :     const uint32_t nSequence{coin_control.m_signal_bip125_rbf.value_or(wallet.m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : CTxIn::MAX_SEQUENCE_NONFINAL};
#     823         [ +  + ]:      22608 :     for (const auto& coin : selected_coins) {
#     824                 :      22608 :         txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence));
#     825                 :      22608 :     }
#     826                 :       5352 :     DiscourageFeeSniping(txNew, rng_fast, wallet.chain(), wallet.GetLastBlockHash(), wallet.GetLastBlockHeight());
#     827                 :            : 
#     828                 :            :     // Calculate the transaction fee
#     829                 :       5352 :     TxSize tx_sizes = CalculateMaximumSignedTxSize(CTransaction(txNew), &wallet, &coin_control);
#     830                 :       5352 :     int nBytes = tx_sizes.vsize;
#     831         [ -  + ]:       5352 :     if (nBytes == -1) {
#     832                 :          0 :         error = _("Missing solving data for estimating transaction size");
#     833                 :          0 :         return false;
#     834                 :          0 :     }
#     835                 :       5352 :     nFeeRet = coin_selection_params.m_effective_feerate.GetFee(nBytes);
#     836                 :            : 
#     837                 :            :     // Subtract fee from the change output if not subtracting it from recipient outputs
#     838                 :       5352 :     CAmount fee_needed = nFeeRet;
#     839         [ +  + ]:       5352 :     if (!coin_selection_params.m_subtract_fee_outputs) {
#     840                 :       4702 :         change_position->nValue -= fee_needed;
#     841                 :       4702 :     }
#     842                 :            : 
#     843                 :            :     // We want to drop the change to fees if:
#     844                 :            :     // 1. The change output would be dust
#     845                 :            :     // 2. The change is within the (almost) exact match window, i.e. it is less than or equal to the cost of the change output (cost_of_change)
#     846                 :       5352 :     CAmount change_amount = change_position->nValue;
#     847 [ +  + ][ +  + ]:       5352 :     if (IsDust(*change_position, coin_selection_params.m_discard_feerate) || change_amount <= coin_selection_params.m_cost_of_change)
#     848                 :        134 :     {
#     849                 :        134 :         nChangePosInOut = -1;
#     850                 :        134 :         change_amount = 0;
#     851                 :        134 :         txNew.vout.erase(change_position);
#     852                 :            : 
#     853                 :            :         // Because we have dropped this change, the tx size and required fee will be different, so let's recalculate those
#     854                 :        134 :         tx_sizes = CalculateMaximumSignedTxSize(CTransaction(txNew), &wallet, &coin_control);
#     855                 :        134 :         nBytes = tx_sizes.vsize;
#     856                 :        134 :         fee_needed = coin_selection_params.m_effective_feerate.GetFee(nBytes);
#     857                 :        134 :     }
#     858                 :            : 
#     859                 :            :     // The only time that fee_needed should be less than the amount available for fees (in change_and_fee - change_amount) is when
#     860                 :            :     // we are subtracting the fee from the outputs. If this occurs at any other time, it is a bug.
#     861                 :       5352 :     assert(coin_selection_params.m_subtract_fee_outputs || fee_needed <= change_and_fee - change_amount);
#     862                 :            : 
#     863                 :            :     // Update nFeeRet in case fee_needed changed due to dropping the change output
#     864         [ +  + ]:       5352 :     if (fee_needed <= change_and_fee - change_amount) {
#     865                 :       4706 :         nFeeRet = change_and_fee - change_amount;
#     866                 :       4706 :     }
#     867                 :            : 
#     868                 :            :     // Reduce output values for subtractFeeFromAmount
#     869         [ +  + ]:       5352 :     if (coin_selection_params.m_subtract_fee_outputs) {
#     870                 :        650 :         CAmount to_reduce = fee_needed + change_amount - change_and_fee;
#     871                 :        650 :         int i = 0;
#     872                 :        650 :         bool fFirst = true;
#     873         [ +  + ]:        650 :         for (const auto& recipient : vecSend)
#     874                 :        662 :         {
#     875         [ +  + ]:        662 :             if (i == nChangePosInOut) {
#     876                 :        285 :                 ++i;
#     877                 :        285 :             }
#     878                 :        662 :             CTxOut& txout = txNew.vout[i];
#     879                 :            : 
#     880         [ +  + ]:        662 :             if (recipient.fSubtractFeeFromAmount)
#     881                 :        658 :             {
#     882                 :        658 :                 txout.nValue -= to_reduce / outputs_to_subtract_fee_from; // Subtract fee equally from each selected recipient
#     883                 :            : 
#     884         [ +  + ]:        658 :                 if (fFirst) // first receiver pays the remainder not divisible by output count
#     885                 :        650 :                 {
#     886                 :        650 :                     fFirst = false;
#     887                 :        650 :                     txout.nValue -= to_reduce % outputs_to_subtract_fee_from;
#     888                 :        650 :                 }
#     889                 :            : 
#     890                 :            :                 // Error if this output is reduced to be below dust
#     891         [ -  + ]:        658 :                 if (IsDust(txout, wallet.chain().relayDustFee())) {
#     892         [ #  # ]:          0 :                     if (txout.nValue < 0) {
#     893                 :          0 :                         error = _("The transaction amount is too small to pay the fee");
#     894                 :          0 :                     } else {
#     895                 :          0 :                         error = _("The transaction amount is too small to send after the fee has been deducted");
#     896                 :          0 :                     }
#     897                 :          0 :                     return false;
#     898                 :          0 :                 }
#     899                 :        658 :             }
#     900                 :        662 :             ++i;
#     901                 :        662 :         }
#     902                 :        650 :         nFeeRet = fee_needed;
#     903                 :        650 :     }
#     904                 :            : 
#     905                 :            :     // Give up if change keypool ran out and change is required
#     906 [ +  + ][ +  + ]:       5352 :     if (scriptChange.empty() && nChangePosInOut != -1) {
#     907                 :          5 :         return false;
#     908                 :          5 :     }
#     909                 :            : 
#     910 [ +  + ][ -  + ]:       5347 :     if (sign && !wallet.SignTransaction(txNew)) {
#     911                 :          0 :         error = _("Signing transaction failed");
#     912                 :          0 :         return false;
#     913                 :          0 :     }
#     914                 :            : 
#     915                 :            :     // Return the constructed transaction data.
#     916                 :       5347 :     tx = MakeTransactionRef(std::move(txNew));
#     917                 :            : 
#     918                 :            :     // Limit size
#     919 [ +  + ][ -  + ]:       5347 :     if ((sign && GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT) ||
#     920 [ +  + ][ +  + ]:       5347 :         (!sign && tx_sizes.weight > MAX_STANDARD_TX_WEIGHT))
#     921                 :          2 :     {
#     922                 :          2 :         error = _("Transaction too large");
#     923                 :          2 :         return false;
#     924                 :          2 :     }
#     925                 :            : 
#     926         [ +  + ]:       5345 :     if (nFeeRet > wallet.m_default_max_tx_fee) {
#     927                 :         38 :         error = TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED);
#     928                 :         38 :         return false;
#     929                 :         38 :     }
#     930                 :            : 
#     931         [ +  + ]:       5307 :     if (gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) {
#     932                 :            :         // Lastly, ensure this tx will pass the mempool's chain limits
#     933         [ +  + ]:       5177 :         if (!wallet.chain().checkChainLimits(tx)) {
#     934                 :          2 :             error = _("Transaction has too long of a mempool chain");
#     935                 :          2 :             return false;
#     936                 :          2 :         }
#     937                 :       5177 :     }
#     938                 :            : 
#     939                 :            :     // Before we return success, we assume any change key will be used to prevent
#     940                 :            :     // accidental re-use.
#     941                 :       5305 :     reservedest.KeepDestination();
#     942                 :       5305 :     fee_calc_out = feeCalc;
#     943                 :            : 
#     944                 :       5305 :     wallet.WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
#     945                 :       5305 :               nFeeRet, nBytes, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
#     946                 :       5305 :               feeCalc.est.pass.start, feeCalc.est.pass.end,
#     947         [ +  + ]:       5305 :               (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) > 0.0 ? 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) : 0.0,
#     948                 :       5305 :               feeCalc.est.pass.withinTarget, feeCalc.est.pass.totalConfirmed, feeCalc.est.pass.inMempool, feeCalc.est.pass.leftMempool,
#     949                 :       5305 :               feeCalc.est.fail.start, feeCalc.est.fail.end,
#     950         [ +  + ]:       5305 :               (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) > 0.0 ? 100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) : 0.0,
#     951                 :       5305 :               feeCalc.est.fail.withinTarget, feeCalc.est.fail.totalConfirmed, feeCalc.est.fail.inMempool, feeCalc.est.fail.leftMempool);
#     952                 :       5305 :     return true;
#     953                 :       5307 : }
#     954                 :            : 
#     955                 :            : bool CreateTransaction(
#     956                 :            :         CWallet& wallet,
#     957                 :            :         const std::vector<CRecipient>& vecSend,
#     958                 :            :         CTransactionRef& tx,
#     959                 :            :         CAmount& nFeeRet,
#     960                 :            :         int& nChangePosInOut,
#     961                 :            :         bilingual_str& error,
#     962                 :            :         const CCoinControl& coin_control,
#     963                 :            :         FeeCalculation& fee_calc_out,
#     964                 :            :         bool sign)
#     965                 :       2830 : {
#     966         [ -  + ]:       2830 :     if (vecSend.empty()) {
#     967                 :          0 :         error = _("Transaction must have at least one recipient");
#     968                 :          0 :         return false;
#     969                 :          0 :     }
#     970                 :            : 
#     971         [ -  + ]:      32478 :     if (std::any_of(vecSend.cbegin(), vecSend.cend(), [](const auto& recipient){ return recipient.nAmount < 0; })) {
#     972                 :          0 :         error = _("Transaction amounts must not be negative");
#     973                 :          0 :         return false;
#     974                 :          0 :     }
#     975                 :            : 
#     976                 :       2830 :     LOCK(wallet.cs_wallet);
#     977                 :            : 
#     978                 :       2830 :     int nChangePosIn = nChangePosInOut;
#     979                 :       2830 :     Assert(!tx); // tx is an out-param. TODO change the return type from bool to tx (or nullptr)
#     980                 :       2830 :     bool res = CreateTransactionInternal(wallet, vecSend, tx, nFeeRet, nChangePosInOut, error, coin_control, fee_calc_out, sign);
#     981                 :            :     // try with avoidpartialspends unless it's enabled already
#     982 [ +  + ][ +  + ]:       2830 :     if (res && nFeeRet > 0 /* 0 means non-functional fee rate estimation */ && wallet.m_max_aps_fee > -1 && !coin_control.m_avoid_partial_spends) {
#         [ +  - ][ +  + ]
#     983                 :       2617 :         CCoinControl tmp_cc = coin_control;
#     984                 :       2617 :         tmp_cc.m_avoid_partial_spends = true;
#     985                 :       2617 :         CAmount nFeeRet2;
#     986                 :       2617 :         CTransactionRef tx2;
#     987                 :       2617 :         int nChangePosInOut2 = nChangePosIn;
#     988                 :       2617 :         bilingual_str error2; // fired and forgotten; if an error occurs, we discard the results
#     989         [ +  + ]:       2617 :         if (CreateTransactionInternal(wallet, vecSend, tx2, nFeeRet2, nChangePosInOut2, error2, tmp_cc, fee_calc_out, sign)) {
#     990                 :            :             // if fee of this alternative one is within the range of the max fee, we use this one
#     991                 :       2612 :             const bool use_aps = nFeeRet2 <= nFeeRet + wallet.m_max_aps_fee;
#     992         [ +  + ]:       2612 :             wallet.WalletLogPrintf("Fee non-grouped = %lld, grouped = %lld, using %s\n", nFeeRet, nFeeRet2, use_aps ? "grouped" : "non-grouped");
#     993         [ +  + ]:       2612 :             if (use_aps) {
#     994                 :       2170 :                 tx = tx2;
#     995                 :       2170 :                 nFeeRet = nFeeRet2;
#     996                 :       2170 :                 nChangePosInOut = nChangePosInOut2;
#     997                 :       2170 :             }
#     998                 :       2612 :         }
#     999                 :       2617 :     }
#    1000                 :       2830 :     return res;
#    1001                 :       2830 : }
#    1002                 :            : 
#    1003                 :            : bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
#    1004                 :        515 : {
#    1005                 :        515 :     std::vector<CRecipient> vecSend;
#    1006                 :            : 
#    1007                 :            :     // Turn the txout set into a CRecipient vector.
#    1008         [ +  + ]:      24254 :     for (size_t idx = 0; idx < tx.vout.size(); idx++) {
#    1009                 :      23739 :         const CTxOut& txOut = tx.vout[idx];
#    1010                 :      23739 :         CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, setSubtractFeeFromOutputs.count(idx) == 1};
#    1011                 :      23739 :         vecSend.push_back(recipient);
#    1012                 :      23739 :     }
#    1013                 :            : 
#    1014                 :        515 :     coinControl.fAllowOtherInputs = true;
#    1015                 :            : 
#    1016         [ +  + ]:        515 :     for (const CTxIn& txin : tx.vin) {
#    1017                 :        274 :         coinControl.Select(txin.prevout);
#    1018                 :        274 :     }
#    1019                 :            : 
#    1020                 :            :     // Acquire the locks to prevent races to the new locked unspents between the
#    1021                 :            :     // CreateTransaction call and LockCoin calls (when lockUnspents is true).
#    1022                 :        515 :     LOCK(wallet.cs_wallet);
#    1023                 :            : 
#    1024                 :        515 :     CTransactionRef tx_new;
#    1025                 :        515 :     FeeCalculation fee_calc_out;
#    1026         [ +  + ]:        515 :     if (!CreateTransaction(wallet, vecSend, tx_new, nFeeRet, nChangePosInOut, error, coinControl, fee_calc_out, false)) {
#    1027                 :         93 :         return false;
#    1028                 :         93 :     }
#    1029                 :            : 
#    1030         [ +  + ]:        422 :     if (nChangePosInOut != -1) {
#    1031                 :        399 :         tx.vout.insert(tx.vout.begin() + nChangePosInOut, tx_new->vout[nChangePosInOut]);
#    1032                 :        399 :     }
#    1033                 :            : 
#    1034                 :            :     // Copy output sizes from new transaction; they may have had the fee
#    1035                 :            :     // subtracted from them.
#    1036         [ +  + ]:      21273 :     for (unsigned int idx = 0; idx < tx.vout.size(); idx++) {
#    1037                 :      20851 :         tx.vout[idx].nValue = tx_new->vout[idx].nValue;
#    1038                 :      20851 :     }
#    1039                 :            : 
#    1040                 :            :     // Add new txins while keeping original txin scriptSig/order.
#    1041         [ +  + ]:        725 :     for (const CTxIn& txin : tx_new->vin) {
#    1042         [ +  + ]:        725 :         if (!coinControl.IsSelected(txin.prevout)) {
#    1043                 :        515 :             tx.vin.push_back(txin);
#    1044                 :            : 
#    1045                 :        515 :         }
#    1046         [ +  + ]:        725 :         if (lockUnspents) {
#    1047                 :          8 :             wallet.LockCoin(txin.prevout);
#    1048                 :          8 :         }
#    1049                 :            : 
#    1050                 :        725 :     }
#    1051                 :            : 
#    1052                 :        422 :     return true;
#    1053                 :        515 : }
#    1054                 :            : } // namespace wallet

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a