LCOV - code coverage report
Current view: top level - src/wallet - receive.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 320 346 92.5 %
Date: 2022-04-21 14:51:19 Functions: 22 22 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: 174 204 85.3 %

           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/consensus.h>
#       7                 :            : #include <wallet/receive.h>
#       8                 :            : #include <wallet/transaction.h>
#       9                 :            : #include <wallet/wallet.h>
#      10                 :            : 
#      11                 :            : namespace wallet {
#      12                 :            : isminetype InputIsMine(const CWallet& wallet, const CTxIn &txin)
#      13                 :        520 : {
#      14                 :        520 :     AssertLockHeld(wallet.cs_wallet);
#      15                 :        520 :     std::map<uint256, CWalletTx>::const_iterator mi = wallet.mapWallet.find(txin.prevout.hash);
#      16         [ +  + ]:        520 :     if (mi != wallet.mapWallet.end())
#      17                 :          7 :     {
#      18                 :          7 :         const CWalletTx& prev = (*mi).second;
#      19         [ +  - ]:          7 :         if (txin.prevout.n < prev.tx->vout.size())
#      20                 :          7 :             return wallet.IsMine(prev.tx->vout[txin.prevout.n]);
#      21                 :          7 :     }
#      22                 :        513 :     return ISMINE_NO;
#      23                 :        520 : }
#      24                 :            : 
#      25                 :            : bool AllInputsMine(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
#      26                 :        313 : {
#      27                 :        313 :     LOCK(wallet.cs_wallet);
#      28                 :            : 
#      29         [ +  + ]:        313 :     for (const CTxIn& txin : tx.vin)
#      30                 :        603 :     {
#      31                 :        603 :         auto mi = wallet.mapWallet.find(txin.prevout.hash);
#      32         [ +  + ]:        603 :         if (mi == wallet.mapWallet.end())
#      33                 :          2 :             return false; // any unknown inputs can't be from us
#      34                 :            : 
#      35                 :        601 :         const CWalletTx& prev = (*mi).second;
#      36                 :            : 
#      37         [ -  + ]:        601 :         if (txin.prevout.n >= prev.tx->vout.size())
#      38                 :          0 :             return false; // invalid input!
#      39                 :            : 
#      40         [ -  + ]:        601 :         if (!(wallet.IsMine(prev.tx->vout[txin.prevout.n]) & filter))
#      41                 :          0 :             return false;
#      42                 :        601 :     }
#      43                 :        311 :     return true;
#      44                 :        313 : }
#      45                 :            : 
#      46                 :            : CAmount OutputGetCredit(const CWallet& wallet, const CTxOut& txout, const isminefilter& filter)
#      47                 :      82546 : {
#      48         [ -  + ]:      82546 :     if (!MoneyRange(txout.nValue))
#      49                 :          0 :         throw std::runtime_error(std::string(__func__) + ": value out of range");
#      50                 :      82546 :     LOCK(wallet.cs_wallet);
#      51         [ +  + ]:      82546 :     return ((wallet.IsMine(txout) & filter) ? txout.nValue : 0);
#      52                 :      82546 : }
#      53                 :            : 
#      54                 :            : CAmount TxGetCredit(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
#      55                 :      16066 : {
#      56                 :      16066 :     CAmount nCredit = 0;
#      57         [ +  + ]:      16066 :     for (const CTxOut& txout : tx.vout)
#      58                 :      32064 :     {
#      59                 :      32064 :         nCredit += OutputGetCredit(wallet, txout, filter);
#      60         [ -  + ]:      32064 :         if (!MoneyRange(nCredit))
#      61                 :          0 :             throw std::runtime_error(std::string(__func__) + ": value out of range");
#      62                 :      32064 :     }
#      63                 :      16066 :     return nCredit;
#      64                 :      16066 : }
#      65                 :            : 
#      66                 :            : bool ScriptIsChange(const CWallet& wallet, const CScript& script)
#      67                 :       3245 : {
#      68                 :            :     // TODO: fix handling of 'change' outputs. The assumption is that any
#      69                 :            :     // payment to a script that is ours, but is not in the address book
#      70                 :            :     // is change. That assumption is likely to break when we implement multisignature
#      71                 :            :     // wallets that return change back into a multi-signature-protected address;
#      72                 :            :     // a better way of identifying which outputs are 'the send' and which are
#      73                 :            :     // 'the change' will need to be implemented (maybe extend CWalletTx to remember
#      74                 :            :     // which output, if any, was change).
#      75                 :       3245 :     AssertLockHeld(wallet.cs_wallet);
#      76         [ +  + ]:       3245 :     if (wallet.IsMine(script))
#      77                 :       2235 :     {
#      78                 :       2235 :         CTxDestination address;
#      79         [ -  + ]:       2235 :         if (!ExtractDestination(script, address))
#      80                 :          0 :             return true;
#      81         [ +  + ]:       2235 :         if (!wallet.FindAddressBookEntry(address)) {
#      82                 :        975 :             return true;
#      83                 :        975 :         }
#      84                 :       2235 :     }
#      85                 :       2270 :     return false;
#      86                 :       3245 : }
#      87                 :            : 
#      88                 :            : bool OutputIsChange(const CWallet& wallet, const CTxOut& txout)
#      89                 :       1925 : {
#      90                 :       1925 :     return ScriptIsChange(wallet, txout.scriptPubKey);
#      91                 :       1925 : }
#      92                 :            : 
#      93                 :            : CAmount OutputGetChange(const CWallet& wallet, const CTxOut& txout)
#      94                 :        216 : {
#      95                 :        216 :     AssertLockHeld(wallet.cs_wallet);
#      96         [ -  + ]:        216 :     if (!MoneyRange(txout.nValue))
#      97                 :          0 :         throw std::runtime_error(std::string(__func__) + ": value out of range");
#      98         [ +  + ]:        216 :     return (OutputIsChange(wallet, txout) ? txout.nValue : 0);
#      99                 :        216 : }
#     100                 :            : 
#     101                 :            : CAmount TxGetChange(const CWallet& wallet, const CTransaction& tx)
#     102                 :        108 : {
#     103                 :        108 :     LOCK(wallet.cs_wallet);
#     104                 :        108 :     CAmount nChange = 0;
#     105         [ +  + ]:        108 :     for (const CTxOut& txout : tx.vout)
#     106                 :        216 :     {
#     107                 :        216 :         nChange += OutputGetChange(wallet, txout);
#     108         [ -  + ]:        216 :         if (!MoneyRange(nChange))
#     109                 :          0 :             throw std::runtime_error(std::string(__func__) + ": value out of range");
#     110                 :        216 :     }
#     111                 :        108 :     return nChange;
#     112                 :        108 : }
#     113                 :            : 
#     114                 :            : static CAmount GetCachableAmount(const CWallet& wallet, const CWalletTx& wtx, CWalletTx::AmountType type, const isminefilter& filter, bool recalculate = false)
#     115                 :    2259519 : {
#     116                 :    2259519 :     auto& amount = wtx.m_amounts[type];
#     117 [ +  + ][ -  + ]:    2259519 :     if (recalculate || !amount.m_cached[filter]) {
#                 [ +  + ]
#     118         [ +  + ]:      77158 :         amount.Set(filter, type == CWalletTx::DEBIT ? wallet.GetDebit(*wtx.tx, filter) : TxGetCredit(wallet, *wtx.tx, filter));
#     119                 :      77158 :         wtx.m_is_cache_empty = false;
#     120                 :      77158 :     }
#     121                 :    2259519 :     return amount.m_value[filter];
#     122                 :    2259519 : }
#     123                 :            : 
#     124                 :            : CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
#     125                 :        582 : {
#     126                 :            :     // Must wait until coinbase is safely deep enough in the chain before valuing it
#     127         [ +  + ]:        582 :     if (wallet.IsTxImmatureCoinBase(wtx))
#     128                 :        116 :         return 0;
#     129                 :            : 
#     130                 :        466 :     CAmount credit = 0;
#     131         [ +  - ]:        466 :     if (filter & ISMINE_SPENDABLE) {
#     132                 :            :         // GetBalance can assume transactions in mapWallet won't change
#     133                 :        466 :         credit += GetCachableAmount(wallet, wtx, CWalletTx::CREDIT, ISMINE_SPENDABLE);
#     134                 :        466 :     }
#     135         [ +  + ]:        466 :     if (filter & ISMINE_WATCH_ONLY) {
#     136                 :         83 :         credit += GetCachableAmount(wallet, wtx, CWalletTx::CREDIT, ISMINE_WATCH_ONLY);
#     137                 :         83 :     }
#     138                 :        466 :     return credit;
#     139                 :        582 : }
#     140                 :            : 
#     141                 :            : CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
#     142                 :    1093681 : {
#     143         [ -  + ]:    1093681 :     if (wtx.tx->vin.empty())
#     144                 :          0 :         return 0;
#     145                 :            : 
#     146                 :    1093681 :     CAmount debit = 0;
#     147         [ +  + ]:    1093681 :     if (filter & ISMINE_SPENDABLE) {
#     148                 :    1075174 :         debit += GetCachableAmount(wallet, wtx, CWalletTx::DEBIT, ISMINE_SPENDABLE);
#     149                 :    1075174 :     }
#     150         [ +  + ]:    1093681 :     if (filter & ISMINE_WATCH_ONLY) {
#     151                 :    1088966 :         debit += GetCachableAmount(wallet, wtx, CWalletTx::DEBIT, ISMINE_WATCH_ONLY);
#     152                 :    1088966 :     }
#     153                 :    1093681 :     return debit;
#     154                 :    1093681 : }
#     155                 :            : 
#     156                 :            : CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx)
#     157                 :        108 : {
#     158         [ -  + ]:        108 :     if (wtx.fChangeCached)
#     159                 :          0 :         return wtx.nChangeCached;
#     160                 :        108 :     wtx.nChangeCached = TxGetChange(wallet, *wtx.tx);
#     161                 :        108 :     wtx.fChangeCached = true;
#     162                 :        108 :     return wtx.nChangeCached;
#     163                 :        108 : }
#     164                 :            : 
#     165                 :            : CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache)
#     166                 :     151500 : {
#     167 [ +  + ][ +  + ]:     151500 :     if (wallet.IsTxImmatureCoinBase(wtx) && wallet.IsTxInMainChain(wtx)) {
#     168                 :      47416 :         return GetCachableAmount(wallet, wtx, CWalletTx::IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache);
#     169                 :      47416 :     }
#     170                 :            : 
#     171                 :     104084 :     return 0;
#     172                 :     151500 : }
#     173                 :            : 
#     174                 :            : CAmount CachedTxGetImmatureWatchOnlyCredit(const CWallet& wallet, const CWalletTx& wtx, const bool fUseCache)
#     175                 :     151498 : {
#     176 [ +  + ][ +  + ]:     151498 :     if (wallet.IsTxImmatureCoinBase(wtx) && wallet.IsTxInMainChain(wtx)) {
#     177                 :      47414 :         return GetCachableAmount(wallet, wtx, CWalletTx::IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache);
#     178                 :      47414 :     }
#     179                 :            : 
#     180                 :     104084 :     return 0;
#     181                 :     151498 : }
#     182                 :            : 
#     183                 :            : CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache, const isminefilter& filter)
#     184                 :     302996 : {
#     185                 :            :     // Avoid caching ismine for NO or ALL cases (could remove this check and simplify in the future).
#     186 [ +  - ][ +  - ]:     302996 :     bool allow_cache = (filter & ISMINE_ALL) && (filter & ISMINE_ALL) != ISMINE_ALL;
#     187                 :            : 
#     188                 :            :     // Must wait until coinbase is safely deep enough in the chain before valuing it
#     189         [ +  + ]:     302996 :     if (wallet.IsTxImmatureCoinBase(wtx))
#     190                 :      94866 :         return 0;
#     191                 :            : 
#     192 [ +  - ][ +  + ]:     208130 :     if (fUseCache && allow_cache && wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_cached[filter]) {
#         [ +  - ][ +  + ]
#     193                 :     174526 :         return wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_value[filter];
#     194                 :     174526 :     }
#     195                 :            : 
#     196 [ +  + ][ +  + ]:      33604 :     bool allow_used_addresses = (filter & ISMINE_USED) || !wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
#     197                 :      33604 :     CAmount nCredit = 0;
#     198                 :      33604 :     uint256 hashTx = wtx.GetHash();
#     199         [ +  + ]:     107448 :     for (unsigned int i = 0; i < wtx.tx->vout.size(); i++)
#     200                 :      73844 :     {
#     201 [ +  + ][ +  + ]:      73844 :         if (!wallet.IsSpent(hashTx, i) && (allow_used_addresses || !wallet.IsSpentKey(hashTx, i))) {
#                 [ +  + ]
#     202                 :      50482 :             const CTxOut &txout = wtx.tx->vout[i];
#     203                 :      50482 :             nCredit += OutputGetCredit(wallet, txout, filter);
#     204         [ -  + ]:      50482 :             if (!MoneyRange(nCredit))
#     205                 :          0 :                 throw std::runtime_error(std::string(__func__) + " : value out of range");
#     206                 :      50482 :         }
#     207                 :      73844 :     }
#     208                 :            : 
#     209         [ +  - ]:      33604 :     if (allow_cache) {
#     210                 :      33604 :         wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].Set(filter, nCredit);
#     211                 :      33604 :         wtx.m_is_cache_empty = false;
#     212                 :      33604 :     }
#     213                 :            : 
#     214                 :      33604 :     return nCredit;
#     215                 :      33604 : }
#     216                 :            : 
#     217                 :            : void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
#     218                 :            :                   std::list<COutputEntry>& listReceived,
#     219                 :            :                   std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter)
#     220                 :      18505 : {
#     221                 :      18505 :     nFee = 0;
#     222                 :      18505 :     listReceived.clear();
#     223                 :      18505 :     listSent.clear();
#     224                 :            : 
#     225                 :            :     // Compute fee:
#     226                 :      18505 :     CAmount nDebit = CachedTxGetDebit(wallet, wtx, filter);
#     227         [ +  + ]:      18505 :     if (nDebit > 0) // debit>0 means we signed/sent this transaction
#     228                 :        730 :     {
#     229                 :        730 :         CAmount nValueOut = wtx.tx->GetValueOut();
#     230                 :        730 :         nFee = nDebit - nValueOut;
#     231                 :        730 :     }
#     232                 :            : 
#     233                 :      18505 :     LOCK(wallet.cs_wallet);
#     234                 :            :     // Sent/received.
#     235         [ +  + ]:      55429 :     for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i)
#     236                 :      36924 :     {
#     237                 :      36924 :         const CTxOut& txout = wtx.tx->vout[i];
#     238                 :      36924 :         isminetype fIsMine = wallet.IsMine(txout);
#     239                 :            :         // Only need to handle txouts if AT LEAST one of these is true:
#     240                 :            :         //   1) they debit from us (sent)
#     241                 :            :         //   2) the output is to us (received)
#     242         [ +  + ]:      36924 :         if (nDebit > 0)
#     243                 :       1368 :         {
#     244                 :            :             // Don't report 'change' txouts
#     245         [ +  + ]:       1368 :             if (OutputIsChange(wallet, txout))
#     246                 :        535 :                 continue;
#     247                 :       1368 :         }
#     248         [ +  + ]:      35556 :         else if (!(fIsMine & filter))
#     249                 :      17774 :             continue;
#     250                 :            : 
#     251                 :            :         // In either case, we need to get the destination address
#     252                 :      18615 :         CTxDestination address;
#     253                 :            : 
#     254 [ +  + ][ -  + ]:      18615 :         if (!ExtractDestination(txout.scriptPubKey, address) && !txout.scriptPubKey.IsUnspendable())
#     255                 :          0 :         {
#     256                 :          0 :             wallet.WalletLogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
#     257                 :          0 :                                     wtx.GetHash().ToString());
#     258                 :          0 :             address = CNoDestination();
#     259                 :          0 :         }
#     260                 :            : 
#     261                 :      18615 :         COutputEntry output = {address, txout.nValue, (int)i};
#     262                 :            : 
#     263                 :            :         // If we are debited by the transaction, add the output as a "sent" entry
#     264         [ +  + ]:      18615 :         if (nDebit > 0)
#     265                 :        833 :             listSent.push_back(output);
#     266                 :            : 
#     267                 :            :         // If we are receiving the output, add it as a "received" entry
#     268         [ +  + ]:      18615 :         if (fIsMine & filter)
#     269                 :      18029 :             listReceived.push_back(output);
#     270                 :      18615 :     }
#     271                 :            : 
#     272                 :      18505 : }
#     273                 :            : 
#     274                 :            : bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
#     275                 :    1074394 : {
#     276                 :    1074394 :     return (CachedTxGetDebit(wallet, wtx, filter) > 0);
#     277                 :    1074394 : }
#     278                 :            : 
#     279                 :            : bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents)
#     280                 :    1188978 : {
#     281                 :    1188978 :     AssertLockHeld(wallet.cs_wallet);
#     282                 :    1188978 :     int nDepth = wallet.GetTxDepthInMainChain(wtx);
#     283         [ +  + ]:    1188978 :     if (nDepth >= 1) return true;
#     284         [ +  + ]:     171923 :     if (nDepth < 0) return false;
#     285                 :            :     // using wtx's cached debit
#     286 [ +  + ][ -  + ]:     171692 :     if (!wallet.m_spend_zero_conf_change || !CachedTxIsFromMe(wallet, wtx, ISMINE_ALL)) return false;
#                 [ +  + ]
#     287                 :            : 
#     288                 :            :     // Don't trust unconfirmed transactions from us unless they are in the mempool.
#     289         [ +  + ]:     166794 :     if (!wtx.InMempool()) return false;
#     290                 :            : 
#     291                 :            :     // Trusted if all inputs are from us and are in the mempool:
#     292         [ +  + ]:     166664 :     for (const CTxIn& txin : wtx.tx->vin)
#     293                 :     179380 :     {
#     294                 :            :         // Transactions not sent by us: not trusted
#     295                 :     179380 :         const CWalletTx* parent = wallet.GetWalletTx(txin.prevout.hash);
#     296         [ -  + ]:     179380 :         if (parent == nullptr) return false;
#     297                 :     179380 :         const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
#     298                 :            :         // Check that this specific input being spent is trusted
#     299         [ +  + ]:     179380 :         if (wallet.IsMine(parentOut) != ISMINE_SPENDABLE) return false;
#     300                 :            :         // If we've already trusted this parent, continue
#     301         [ +  + ]:     179373 :         if (trusted_parents.count(parent->GetHash())) continue;
#     302                 :            :         // Recurse to check that the parent is also trusted
#     303         [ +  + ]:     143801 :         if (!CachedTxIsTrusted(wallet, *parent, trusted_parents)) return false;
#     304                 :     143743 :         trusted_parents.insert(parent->GetHash());
#     305                 :     143743 :     }
#     306                 :     166599 :     return true;
#     307                 :     166664 : }
#     308                 :            : 
#     309                 :            : bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx)
#     310                 :       1143 : {
#     311                 :       1143 :     std::set<uint256> trusted_parents;
#     312                 :       1143 :     LOCK(wallet.cs_wallet);
#     313                 :       1143 :     return CachedTxIsTrusted(wallet, wtx, trusted_parents);
#     314                 :       1143 : }
#     315                 :            : 
#     316                 :            : Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
#     317                 :       2737 : {
#     318                 :       2737 :     Balance ret;
#     319         [ +  + ]:       2737 :     isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED;
#     320                 :       2737 :     {
#     321                 :       2737 :         LOCK(wallet.cs_wallet);
#     322                 :       2737 :         std::set<uint256> trusted_parents;
#     323         [ +  + ]:       2737 :         for (const auto& entry : wallet.mapWallet)
#     324                 :     151498 :         {
#     325                 :     151498 :             const CWalletTx& wtx = entry.second;
#     326                 :     151498 :             const bool is_trusted{CachedTxIsTrusted(wallet, wtx, trusted_parents)};
#     327                 :     151498 :             const int tx_depth{wallet.GetTxDepthInMainChain(wtx)};
#     328                 :     151498 :             const CAmount tx_credit_mine{CachedTxGetAvailableCredit(wallet, wtx, /*fUseCache=*/true, ISMINE_SPENDABLE | reuse_filter)};
#     329                 :     151498 :             const CAmount tx_credit_watchonly{CachedTxGetAvailableCredit(wallet, wtx, /*fUseCache=*/true, ISMINE_WATCH_ONLY | reuse_filter)};
#     330 [ +  + ][ +  + ]:     151498 :             if (is_trusted && tx_depth >= min_depth) {
#     331                 :     150322 :                 ret.m_mine_trusted += tx_credit_mine;
#     332                 :     150322 :                 ret.m_watchonly_trusted += tx_credit_watchonly;
#     333                 :     150322 :             }
#     334 [ +  + ][ +  + ]:     151498 :             if (!is_trusted && tx_depth == 0 && wtx.InMempool()) {
#                 [ +  + ]
#     335                 :        863 :                 ret.m_mine_untrusted_pending += tx_credit_mine;
#     336                 :        863 :                 ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
#     337                 :        863 :             }
#     338                 :     151498 :             ret.m_mine_immature += CachedTxGetImmatureCredit(wallet, wtx);
#     339                 :     151498 :             ret.m_watchonly_immature += CachedTxGetImmatureWatchOnlyCredit(wallet, wtx);
#     340                 :     151498 :         }
#     341                 :       2737 :     }
#     342                 :       2737 :     return ret;
#     343                 :       2737 : }
#     344                 :            : 
#     345                 :            : std::map<CTxDestination, CAmount> GetAddressBalances(const CWallet& wallet)
#     346                 :          4 : {
#     347                 :          4 :     std::map<CTxDestination, CAmount> balances;
#     348                 :            : 
#     349                 :          4 :     {
#     350                 :          4 :         LOCK(wallet.cs_wallet);
#     351                 :          4 :         std::set<uint256> trusted_parents;
#     352         [ +  + ]:          4 :         for (const auto& walletEntry : wallet.mapWallet)
#     353                 :        410 :         {
#     354                 :        410 :             const CWalletTx& wtx = walletEntry.second;
#     355                 :            : 
#     356         [ -  + ]:        410 :             if (!CachedTxIsTrusted(wallet, wtx, trusted_parents))
#     357                 :          0 :                 continue;
#     358                 :            : 
#     359         [ +  + ]:        410 :             if (wallet.IsTxImmatureCoinBase(wtx))
#     360                 :        400 :                 continue;
#     361                 :            : 
#     362                 :         10 :             int nDepth = wallet.GetTxDepthInMainChain(wtx);
#     363 [ -  + ][ +  + ]:         10 :             if (nDepth < (CachedTxIsFromMe(wallet, wtx, ISMINE_ALL) ? 0 : 1))
#     364                 :          0 :                 continue;
#     365                 :            : 
#     366         [ +  + ]:         28 :             for (unsigned int i = 0; i < wtx.tx->vout.size(); i++)
#     367                 :         18 :             {
#     368                 :         18 :                 CTxDestination addr;
#     369         [ +  + ]:         18 :                 if (!wallet.IsMine(wtx.tx->vout[i]))
#     370                 :         10 :                     continue;
#     371         [ -  + ]:          8 :                 if(!ExtractDestination(wtx.tx->vout[i].scriptPubKey, addr))
#     372                 :          0 :                     continue;
#     373                 :            : 
#     374         [ +  + ]:          8 :                 CAmount n = wallet.IsSpent(walletEntry.first, i) ? 0 : wtx.tx->vout[i].nValue;
#     375                 :          8 :                 balances[addr] += n;
#     376                 :          8 :             }
#     377                 :         10 :         }
#     378                 :          4 :     }
#     379                 :            : 
#     380                 :          4 :     return balances;
#     381                 :          4 : }
#     382                 :            : 
#     383                 :            : std::set< std::set<CTxDestination> > GetAddressGroupings(const CWallet& wallet)
#     384                 :          4 : {
#     385                 :          4 :     AssertLockHeld(wallet.cs_wallet);
#     386                 :          4 :     std::set< std::set<CTxDestination> > groupings;
#     387                 :          4 :     std::set<CTxDestination> grouping;
#     388                 :            : 
#     389         [ +  + ]:          4 :     for (const auto& walletEntry : wallet.mapWallet)
#     390                 :        410 :     {
#     391                 :        410 :         const CWalletTx& wtx = walletEntry.second;
#     392                 :            : 
#     393         [ +  - ]:        410 :         if (wtx.tx->vin.size() > 0)
#     394                 :        410 :         {
#     395                 :        410 :             bool any_mine = false;
#     396                 :            :             // group all input addresses with each other
#     397         [ +  + ]:        410 :             for (const CTxIn& txin : wtx.tx->vin)
#     398                 :        412 :             {
#     399                 :        412 :                 CTxDestination address;
#     400         [ +  + ]:        412 :                 if(!InputIsMine(wallet, txin)) /* If this input isn't mine, ignore it */
#     401                 :        408 :                     continue;
#     402         [ -  + ]:          4 :                 if(!ExtractDestination(wallet.mapWallet.at(txin.prevout.hash).tx->vout[txin.prevout.n].scriptPubKey, address))
#     403                 :          0 :                     continue;
#     404                 :          4 :                 grouping.insert(address);
#     405                 :          4 :                 any_mine = true;
#     406                 :          4 :             }
#     407                 :            : 
#     408                 :            :             // group change with input addresses
#     409         [ +  + ]:        410 :             if (any_mine)
#     410                 :          2 :             {
#     411         [ +  + ]:          2 :                for (const CTxOut& txout : wtx.tx->vout)
#     412         [ -  + ]:          2 :                    if (OutputIsChange(wallet, txout))
#     413                 :          0 :                    {
#     414                 :          0 :                        CTxDestination txoutAddr;
#     415         [ #  # ]:          0 :                        if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
#     416                 :          0 :                            continue;
#     417                 :          0 :                        grouping.insert(txoutAddr);
#     418                 :          0 :                    }
#     419                 :          2 :             }
#     420         [ +  + ]:        410 :             if (grouping.size() > 0)
#     421                 :          2 :             {
#     422                 :          2 :                 groupings.insert(grouping);
#     423                 :          2 :                 grouping.clear();
#     424                 :          2 :             }
#     425                 :        410 :         }
#     426                 :            : 
#     427                 :            :         // group lone addrs by themselves
#     428         [ +  + ]:        410 :         for (const auto& txout : wtx.tx->vout)
#     429         [ +  + ]:        818 :             if (wallet.IsMine(txout))
#     430                 :        408 :             {
#     431                 :        408 :                 CTxDestination address;
#     432         [ -  + ]:        408 :                 if(!ExtractDestination(txout.scriptPubKey, address))
#     433                 :          0 :                     continue;
#     434                 :        408 :                 grouping.insert(address);
#     435                 :        408 :                 groupings.insert(grouping);
#     436                 :        408 :                 grouping.clear();
#     437                 :        408 :             }
#     438                 :        410 :     }
#     439                 :            : 
#     440                 :          4 :     std::set< std::set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
#     441                 :          4 :     std::map< CTxDestination, std::set<CTxDestination>* > setmap;  // map addresses to the unique group containing it
#     442         [ +  + ]:          4 :     for (std::set<CTxDestination> _grouping : groupings)
#     443                 :         10 :     {
#     444                 :            :         // make a set of all the groups hit by this new group
#     445                 :         10 :         std::set< std::set<CTxDestination>* > hits;
#     446                 :         10 :         std::map< CTxDestination, std::set<CTxDestination>* >::iterator it;
#     447         [ +  + ]:         10 :         for (const CTxDestination& address : _grouping)
#     448         [ +  + ]:         12 :             if ((it = setmap.find(address)) != setmap.end())
#     449                 :          4 :                 hits.insert((*it).second);
#     450                 :            : 
#     451                 :            :         // merge all hit groups into a new single group and delete old groups
#     452                 :         10 :         std::set<CTxDestination>* merged = new std::set<CTxDestination>(_grouping);
#     453         [ +  + ]:         10 :         for (std::set<CTxDestination>* hit : hits)
#     454                 :          4 :         {
#     455                 :          4 :             merged->insert(hit->begin(), hit->end());
#     456                 :          4 :             uniqueGroupings.erase(hit);
#     457                 :          4 :             delete hit;
#     458                 :          4 :         }
#     459                 :         10 :         uniqueGroupings.insert(merged);
#     460                 :            : 
#     461                 :            :         // update setmap
#     462         [ +  + ]:         10 :         for (const CTxDestination& element : *merged)
#     463                 :         14 :             setmap[element] = merged;
#     464                 :         10 :     }
#     465                 :            : 
#     466                 :          4 :     std::set< std::set<CTxDestination> > ret;
#     467         [ +  + ]:          4 :     for (const std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
#     468                 :          6 :     {
#     469                 :          6 :         ret.insert(*uniqueGrouping);
#     470                 :          6 :         delete uniqueGrouping;
#     471                 :          6 :     }
#     472                 :            : 
#     473                 :          4 :     return ret;
#     474                 :          4 : }
#     475                 :            : } // namespace wallet

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