LCOV - code coverage report
Current view: top level - src/wallet - spend.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 548 607 90.3 %
Date: 2021-06-29 14:35:33 Functions: 16 17 94.1 %
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: 330 394 83.8 %

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

Generated by: LCOV version 1.14