LCOV - code coverage report
Current view: top level - src/wallet - transaction.h (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 79.3 % 164 130
Test Date: 2026-10-07 06:45:19 Functions: 80.0 % 20 16
Branches: 29.0 % 594 172

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2021-present 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                 :             : #ifndef BITCOIN_WALLET_TRANSACTION_H
       6                 :             : #define BITCOIN_WALLET_TRANSACTION_H
       7                 :             : 
       8                 :             : #include <attributes.h>
       9                 :             : #include <consensus/amount.h>
      10                 :             : #include <primitives/transaction.h>
      11                 :             : #include <tinyformat.h>
      12                 :             : #include <uint256.h>
      13                 :             : #include <util/check.h>
      14                 :             : #include <util/overloaded.h>
      15                 :             : #include <util/strencodings.h>
      16                 :             : #include <util/string.h>
      17                 :             : #include <wallet/types.h>
      18                 :             : 
      19                 :             : #include <bitset>
      20                 :             : #include <cstdint>
      21                 :             : #include <map>
      22                 :             : #include <utility>
      23                 :             : #include <variant>
      24                 :             : #include <vector>
      25                 :             : 
      26                 :             : namespace interfaces {
      27                 :             : class Chain;
      28                 :             : } // namespace interfaces
      29                 :             : 
      30                 :             : namespace wallet {
      31                 :             : class WalletBatch;
      32                 :             : 
      33                 :             : //! State of transaction confirmed in a block.
      34                 :             : struct TxStateConfirmed {
      35                 :             :     uint256 confirmed_block_hash;
      36                 :             :     int confirmed_block_height;
      37                 :             :     int position_in_block;
      38                 :             : 
      39         [ +  - ]:         856 :     explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
      40         [ +  - ]:        1648 :     std::string toString() const { return strprintf("Confirmed (block=%s, height=%i, index=%i)", confirmed_block_hash.ToString(), confirmed_block_height, position_in_block); }
      41                 :             : };
      42                 :             : 
      43                 :             : //! State of transaction added to mempool.
      44                 :             : struct TxStateInMempool {
      45                 :           6 :     std::string toString() const { return strprintf("InMempool"); }
      46                 :             : };
      47                 :             : 
      48                 :             : //! State of rejected transaction that conflicts with a confirmed block.
      49                 :             : struct TxStateBlockConflicted {
      50                 :             :     uint256 conflicting_block_hash;
      51                 :             :     int conflicting_block_height;
      52                 :             : 
      53                 :           3 :     explicit TxStateBlockConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
      54         [ #  # ]:           0 :     std::string toString() const { return strprintf("BlockConflicted (block=%s, height=%i)", conflicting_block_hash.ToString(), conflicting_block_height); }
      55                 :             : };
      56                 :             : 
      57                 :             : //! State of transaction not confirmed or conflicting with a known block and
      58                 :             : //! not in the mempool. May conflict with the mempool, or with an unknown block,
      59                 :             : //! or be abandoned, never broadcast, or rejected from the mempool for another
      60                 :             : //! reason.
      61                 :             : struct TxStateInactive {
      62                 :             :     bool abandoned;
      63                 :             : 
      64         [ +  - ]:      116259 :     explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
           [ +  -  +  - ]
           [ -  -  +  -  
          -  -  -  -  -  
             -  -  -  -  
                      - ]
      65                 :           6 :     std::string toString() const { return strprintf("Inactive (abandoned=%i)", abandoned); }
      66                 :             : };
      67                 :             : 
      68                 :             : //! State of transaction loaded in an unrecognized state with unexpected hash or
      69                 :             : //! index values. Treated as inactive (with serialized hash and index values
      70                 :             : //! preserved) by default, but may enter another state if transaction is added
      71                 :             : //! to the mempool, or confirmed, or abandoned, or found conflicting.
      72                 :             : struct TxStateUnrecognized {
      73                 :             :     uint256 block_hash;
      74                 :             :     int index;
      75                 :             : 
      76                 :          25 :     TxStateUnrecognized(const uint256& block_hash, int index) : block_hash(block_hash), index(index) {}
      77         [ #  # ]:           0 :     std::string toString() const { return strprintf("Unrecognized (block=%s, index=%i)", block_hash.ToString(), index); }
      78                 :             : };
      79                 :             : 
      80                 :             : //! All possible CWalletTx states
      81                 :             : using TxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized>;
      82                 :             : 
      83                 :             : //! Subset of states transaction sync logic is implemented to handle.
      84                 :             : using SyncTxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateInactive>;
      85                 :             : 
      86                 :             : //! Try to interpret deserialized TxStateUnrecognized data as a recognized state.
      87                 :          28 : static inline TxState TxStateInterpretSerialized(TxStateUnrecognized data)
      88                 :             : {
      89         [ +  + ]:          28 :     if (data.block_hash == uint256::ZERO) {
      90         [ +  + ]:           7 :         if (data.index == 0) return TxStateInactive{};
      91         [ +  + ]:          21 :     } else if (data.block_hash == uint256::ONE) {
      92         [ +  + ]:           5 :         if (data.index == -1) return TxStateInactive{/*abandoned=*/true};
      93         [ +  + ]:          16 :     } else if (data.index >= 0) {
      94                 :          10 :         return TxStateConfirmed{data.block_hash, /*height=*/-1, data.index};
      95         [ +  + ]:           6 :     } else if (data.index == -1) {
      96                 :           3 :         return TxStateBlockConflicted{data.block_hash, /*height=*/-1};
      97                 :             :     }
      98                 :          11 :     return data;
      99                 :             : }
     100                 :             : 
     101                 :             : //! Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
     102                 :         863 : static inline uint256 TxStateSerializedBlockHash(const TxState& state)
     103                 :             : {
     104         [ +  + ]:          31 :     return std::visit(util::Overloaded{
     105         [ +  + ]:          17 :         [](const TxStateInactive& inactive) { return inactive.abandoned ? uint256::ONE : uint256::ZERO; },
     106                 :          10 :         [](const TxStateInMempool& in_mempool) { return uint256::ZERO; },
     107                 :         836 :         [](const TxStateConfirmed& confirmed) { return confirmed.confirmed_block_hash; },
     108                 :           3 :         [](const TxStateBlockConflicted& conflicted) { return conflicted.conflicting_block_hash; },
     109                 :          11 :         [](const TxStateUnrecognized& unrecognized) { return unrecognized.block_hash; }
     110                 :             :     }, state);
     111                 :             : }
     112                 :             : 
     113                 :             : //! Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
     114                 :         863 : static inline int TxStateSerializedIndex(const TxState& state)
     115                 :             : {
     116         [ +  + ]:          31 :     return std::visit(util::Overloaded{
     117         [ +  + ]:           9 :         [](const TxStateInactive& inactive) { return inactive.abandoned ? -1 : 0; },
     118                 :             :         [](const TxStateInMempool& in_mempool) { return 0; },
     119                 :         836 :         [](const TxStateConfirmed& confirmed) { return confirmed.position_in_block; },
     120                 :             :         [](const TxStateBlockConflicted& conflicted) { return -1; },
     121                 :          11 :         [](const TxStateUnrecognized& unrecognized) { return unrecognized.index; }
     122                 :             :     }, state);
     123                 :             : }
     124                 :             : 
     125                 :             : //! Return TxState or SyncTxState as a string for logging or debugging.
     126                 :             : template<typename T>
     127                 :         836 : std::string TxStateString(const T& state)
     128                 :             : {
     129                 :         836 :     return std::visit([](const auto& s) { return s.toString(); }, state);
     130                 :             : }
     131                 :             : 
     132                 :             : /**
     133                 :             :  * Cachable amount subdivided into avoid reuse and all balances
     134                 :             :  */
     135                 :             : struct CachableAmount
     136                 :             : {
     137                 :             :     std::optional<CAmount> m_avoid_reuse_value;
     138                 :             :     std::optional<CAmount> m_all_value;
     139                 :        1694 :     inline void Reset()
     140                 :             :     {
     141                 :        3388 :         m_avoid_reuse_value.reset();
     142   [ -  +  -  + ]:        1694 :         m_all_value.reset();
     143                 :             :     }
     144                 :           0 :     void Set(bool avoid_reuse, CAmount value)
     145                 :             :     {
     146         [ #  # ]:           0 :         if (avoid_reuse) {
     147                 :           0 :             m_avoid_reuse_value = value;
     148                 :             :         } else {
     149                 :           0 :             m_all_value = value;
     150                 :             :         }
     151                 :             :     }
     152                 :           0 :     CAmount Get(bool avoid_reuse)
     153                 :             :     {
     154         [ #  # ]:           0 :         if (avoid_reuse) {
     155         [ #  # ]:           0 :             Assert(m_avoid_reuse_value.has_value());
     156                 :           0 :             return m_avoid_reuse_value.value();
     157                 :             :         }
     158         [ #  # ]:           0 :         Assert(m_all_value.has_value());
     159                 :           0 :         return m_all_value.value();
     160                 :             :     }
     161                 :           0 :     bool IsCached(bool avoid_reuse)
     162                 :             :     {
     163         [ #  # ]:           0 :         if (avoid_reuse) return m_avoid_reuse_value.has_value();
     164                 :           0 :         return m_all_value.has_value();
     165                 :             :     }
     166                 :             : };
     167                 :             : 
     168                 :             : 
     169                 :             : /** Legacy class used for deserializing vtxPrev for backwards compatibility.
     170                 :             :  * vtxPrev was removed in commit 93a18a3650292afbb441a47d1fa1b94aeb0164e3,
     171                 :             :  * but old wallet.dat files may still contain vtxPrev vectors of CMerkleTxs.
     172                 :             :  * These need to get deserialized for field alignment when deserializing
     173                 :             :  * a CWalletTx, but the deserialized values are discarded.**/
     174                 :             : class CMerkleTx
     175                 :             : {
     176                 :             : public:
     177                 :             :     template<typename Stream>
     178                 :           0 :     void Unserialize(Stream& s)
     179                 :             :     {
     180                 :           0 :         CTransactionRef tx;
     181                 :           0 :         uint256 hashBlock;
     182         [ #  # ]:           0 :         std::vector<uint256> vMerkleBranch;
     183                 :             :         int nIndex;
     184                 :             : 
     185   [ #  #  #  #  :           0 :         s >> TX_WITH_WITNESS(tx) >> hashBlock >> vMerkleBranch >> nIndex;
             #  #  #  # ]
     186         [ #  # ]:           0 :     }
     187                 :             : };
     188                 :             : 
     189                 :             : /**
     190                 :             :  * A transaction with a bunch of additional info that only the owner cares about.
     191                 :             :  * It includes any unrecorded transactions needed to link it back to the block chain.
     192                 :             :  */
     193                 :             : class CWalletTx
     194                 :             : {
     195                 :             : public:
     196                 :             :     // "from" and "message" are obsolete fields that could be set in
     197                 :             :     // the UI prior to 2011 (removed in commit 4d9b223)
     198                 :             :     // These fields are kept to avoid losing metadata.
     199                 :             :     std::optional<std::string> m_from;
     200                 :             :     std::optional<std::string> m_message;
     201                 :             :     // Comment strings provided by the user
     202                 :             :     std::optional<std::string> m_comment;
     203                 :             :     std::optional<std::string> m_comment_to;
     204                 :             :     std::optional<Txid> m_replaces_txid;
     205                 :             :     std::optional<Txid> m_replaced_by_txid;
     206                 :             :     // BIP 21 URI Messages
     207                 :             :     std::vector<std::string> m_messages;
     208                 :             :     // BIP 70 Payment Request (deprecated, field kept to preserve metadata from old wallets)
     209                 :             :     std::vector<std::string> m_payment_requests;
     210                 :             :     unsigned int nTimeReceived; //!< time received by this node
     211                 :             :     /**
     212                 :             :      * Stable timestamp that never changes, and reflects the order a transaction
     213                 :             :      * was added to the wallet. Timestamp is based on the block time for a
     214                 :             :      * transaction added as part of a block, or else the time when the
     215                 :             :      * transaction was received if it wasn't part of a block, with the timestamp
     216                 :             :      * adjusted in both cases so timestamp order matches the order transactions
     217                 :             :      * were added to the wallet. More details can be found in
     218                 :             :      * CWallet::ComputeTimeSmart().
     219                 :             :      */
     220                 :             :     unsigned int nTimeSmart;
     221                 :             :     // Cached value for whether the transaction spends any inputs known to the wallet
     222                 :             :     mutable std::optional<bool> m_cached_from_me{std::nullopt};
     223                 :             :     int64_t nOrderPos; //!< position in ordered transaction list
     224                 :             :     std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
     225                 :             : 
     226                 :             :     // memory only
     227                 :             :     enum AmountType { DEBIT, CREDIT, AMOUNTTYPE_ENUM_ELEMENTS };
     228                 :             :     mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS];
     229                 :             :     /**
     230                 :             :      * This flag is true if all m_amounts caches are empty. This is particularly
     231                 :             :      * useful in places where MarkDirty is conditionally called and the
     232                 :             :      * condition can be expensive and thus can be skipped if the flag is true.
     233                 :             :      * See MarkDestinationsDirty.
     234                 :             :      */
     235                 :             :     mutable bool m_is_cache_empty{true};
     236                 :             :     mutable bool fChangeCached;
     237                 :             :     mutable CAmount nChangeCached;
     238                 :             : 
     239         [ -  + ]:      117081 :     CWalletTx(CTransactionRef tx, const TxState& state) : m_state(state)
     240                 :             :     {
     241         [ -  + ]:      117081 :         Assert(tx);
     242         [ +  - ]:      117081 :         m_canonical_wtxid = tx->GetWitnessHash();
     243         [ +  - ]:      117081 :         m_txs.emplace(tx->GetWitnessHash(), std::move(tx));
     244                 :      117081 :         SetDefaults();
     245                 :           0 :     }
     246                 :             : 
     247                 :             :     template <typename Stream>
     248         [ +  - ]:           3 :     CWalletTx(deserialize_type, Stream& s, const std::map<Wtxid, CTransactionRef>& variants) : m_state(TxStateInactive{})
     249                 :             :     {
     250         [ +  - ]:           3 :         Unserialize(s);
     251         [ +  - ]:           3 :         const Txid& canonical_txid = GetHash();
     252   [ +  +  +  + ]:           5 :         for (const auto& [wtxid, tx] : variants) {
     253   [ +  +  +  - ]:           3 :             if (tx->GetHash() != canonical_txid) throw std::runtime_error("variant txid does not match wallet txid");
     254                 :             :         }
     255                 :             :         // Merge witness variants
     256         [ +  - ]:           2 :         m_txs.insert(variants.begin(), variants.end());
     257   [ +  -  -  + ]:           2 :         Assert(m_txs.contains(GetWitnessHash()));
     258                 :           5 :     }
     259                 :             : 
     260                 :             :     TxState m_state;
     261                 :             : 
     262                 :             :     // Set of mempool transactions that conflict
     263                 :             :     // directly with the transaction, or that conflict
     264                 :             :     // with an ancestor transaction. This set will be
     265                 :             :     // empty if state is InMempool or Confirmed, but
     266                 :             :     // can be nonempty if state is Inactive or
     267                 :             :     // BlockConflicted.
     268                 :             :     std::set<Txid> mempool_conflicts;
     269                 :             : 
     270                 :             :     // Track v3 mempool tx that spends from this tx
     271                 :             :     // so that we don't try to create another unconfirmed child
     272                 :             :     std::optional<Txid> truc_child_in_mempool;
     273                 :             : 
     274                 :             :     template<typename Stream>
     275         [ -  + ]:         832 :     void Serialize(Stream& s) const
     276                 :             :     {
     277                 :         832 :         std::map<std::string, std::string> string_values;
     278   [ -  +  -  -  :         832 :         if (m_from) string_values["from"] = *m_from;
             -  -  -  - ]
     279   [ -  +  -  -  :         832 :         if (m_message) string_values["message"] = *m_message;
             -  -  -  - ]
     280   [ -  +  -  -  :         832 :         if (m_comment) string_values["comment"] = *m_comment;
             -  -  -  - ]
     281   [ -  +  -  -  :         832 :         if (m_comment_to) string_values["to"] = *m_comment_to;
             -  -  -  - ]
     282   [ -  +  -  -  :         832 :         if (m_replaces_txid) string_values["replaces_txid"] = m_replaces_txid->ToString();
             -  -  -  - ]
     283   [ -  +  -  -  :         832 :         if (m_replaced_by_txid) string_values["replaced_by_txid"] = m_replaced_by_txid->ToString();
             -  -  -  - ]
     284   [ +  -  +  -  :         832 :         string_values["fromaccount"] = "";
                   +  - ]
     285   [ +  +  +  -  :         832 :         if (nOrderPos != -1) string_values["n"] = util::ToString(nOrderPos);
             +  -  +  - ]
     286   [ +  +  +  -  :         832 :         if (nTimeSmart) string_values["timesmart"] = strprintf("%u", nTimeSmart);
             +  -  +  - ]
     287                 :             : 
     288                 :         832 :         std::vector<std::pair<std::string, std::string>> msgs_reqs;
     289   [ -  +  -  +  :         832 :         msgs_reqs.reserve(m_messages.size() + m_payment_requests.size());
                   +  - ]
     290         [ -  + ]:         832 :         for (const std::string& msg : m_messages) {
     291         [ #  # ]:           0 :             msgs_reqs.emplace_back("Message", msg);
     292                 :             :         }
     293         [ -  + ]:         832 :         for (const std::string& req : m_payment_requests) {
     294         [ #  # ]:           0 :             msgs_reqs.emplace_back("PaymentRequest", req);
     295                 :             :         }
     296                 :             : 
     297                 :         832 :         std::vector<uint8_t> dummy_vector1; // Used to be vMerkleBranch
     298                 :         832 :         std::vector<uint8_t> dummy_vector2; // Used to be vtxPrev
     299                 :         832 :         bool dummy_bool = false; // Used to be fFromMe, and fSpent
     300                 :         832 :         uint32_t dummy_int = 0; // Used to be fTimeReceivedIsTxTime
     301         [ +  - ]:         832 :         uint256 serializedHash = TxStateSerializedBlockHash(m_state);
     302                 :         832 :         int serializedIndex = TxStateSerializedIndex(m_state);
     303   [ +  -  +  -  :        2496 :         s << TX_WITH_WITNESS(GetTx()) << serializedHash << dummy_vector1 << serializedIndex << dummy_vector2 << string_values << msgs_reqs << dummy_int << nTimeReceived << dummy_bool << dummy_bool;
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     304                 :         832 :     }
     305                 :             : 
     306                 :             :     template<typename Stream>
     307                 :           3 :     void Unserialize(Stream& s)
     308                 :             :     {
     309                 :           3 :         Init();
     310                 :             : 
     311                 :           3 :         std::vector<uint256> dummy_vector1; // Used to be vMerkleBranch
     312                 :           3 :         std::vector<CMerkleTx> dummy_vector2; // Used to be vtxPrev
     313                 :             :         bool dummy_bool; // Used to be fFromMe, and fSpent
     314                 :             :         uint32_t dummy_int; // Used to be fTimeReceivedIsTxTime
     315         [ +  - ]:           3 :         uint256 serialized_block_hash;
     316                 :             :         int serializedIndex;
     317                 :           3 :         std::map<std::string, std::string> string_values;
     318                 :           3 :         std::vector<std::pair<std::string, std::string>> msgs_reqs;
     319         [ +  - ]:           3 :         CTransactionRef canonical_tx;
     320   [ +  -  +  -  :           6 :         s >> TX_WITH_WITNESS(canonical_tx) >> serialized_block_hash >> dummy_vector1 >> serializedIndex >> dummy_vector2 >> string_values >> msgs_reqs >> dummy_int >> nTimeReceived >> dummy_bool >> dummy_bool;
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     321                 :           3 :         m_canonical_wtxid = canonical_tx->GetWitnessHash();
     322         [ +  - ]:           3 :         m_txs.emplace(m_canonical_wtxid, std::move(canonical_tx));
     323                 :             : 
     324                 :           3 :         m_state = TxStateInterpretSerialized({serialized_block_hash, serializedIndex});
     325                 :             : 
     326         [ +  - ]:           6 :         string_values.erase("fromaccount");
     327         [ +  - ]:           6 :         string_values.erase("spent");
     328   [ +  +  +  + ]:           7 :         for (const auto& [key, value] : string_values) {
     329   [ +  +  +  - ]:           6 :             if (key == "n") nOrderPos = LocaleIndependentAtoi<int64_t>(value);
     330   [ +  -  +  - ]:           4 :             else if (key == "timesmart") nTimeSmart = LocaleIndependentAtoi<int64_t>(value);
     331   [ #  #  #  # ]:           0 :             else if (key == "from") m_from = value;
     332   [ #  #  #  # ]:           0 :             else if (key == "message") m_message = value;
     333   [ #  #  #  # ]:           0 :             else if (key == "comment") m_comment = value;
     334   [ #  #  #  # ]:           0 :             else if (key == "to") m_comment_to = value;
     335   [ #  #  #  # ]:           0 :             else if (key == "replaces_txid") m_replaces_txid = Txid::FromHex(value);
     336   [ #  #  #  # ]:           0 :             else if (key == "replaced_by_txid") m_replaced_by_txid = Txid::FromHex(value);
     337                 :             :             else {
     338         [ #  # ]:           0 :                 throw std::runtime_error("Unexpected value in CWalletTx strings value map");
     339                 :             :             }
     340                 :             :         }
     341                 :             : 
     342   [ -  -  -  + ]:           3 :         for (const auto& [type, data] : msgs_reqs) {
     343   [ #  #  #  # ]:           0 :             if (type == "Message") m_messages.emplace_back(data);
     344   [ #  #  #  # ]:           0 :             else if (type == "PaymentRequest") m_payment_requests.emplace_back(data);
     345                 :             :             else {
     346         [ #  # ]:           0 :                 throw std::runtime_error("Unknown type in CWalletTx messages and requests vector");
     347                 :             :             }
     348                 :             :         }
     349                 :           3 :     }
     350                 :             : 
     351         [ +  - ]:      246394 :     CTransactionRef GetTx() const { return m_txs.at(m_canonical_wtxid); }
     352                 :             : 
     353                 :             :     // Update the state of this wallet transaction along with a transaction that may have a different wtxid.
     354                 :             :     // If the given transaction has a different wtxid, the transaction is stored if it has not been seen before.
     355                 :             :     // The canonical wtxid is also updated. The tx that is confirmed becomes canonical. For unconfirmed txs,
     356                 :             :     // those with witnesses are preferred, followed by least weight.
     357                 :             :     bool Update(CTransactionRef tx, const TxState& new_state, WalletBatch& batch, bool metadata_changed);
     358                 :             : 
     359                 :             :     //! make sure balances are recalculated
     360                 :         847 :     void MarkDirty()
     361                 :             :     {
     362         [ -  + ]:         847 :         m_amounts[DEBIT].Reset();
     363         [ -  + ]:         847 :         m_amounts[CREDIT].Reset();
     364                 :         847 :         fChangeCached = false;
     365                 :         847 :         m_is_cache_empty = true;
     366         [ +  + ]:         847 :         m_cached_from_me = std::nullopt;
     367                 :         847 :     }
     368                 :             : 
     369                 :             :     /** True if tx is a malleation of this, i.e. it has the exact same version, locktime,
     370                 :             :      * input order, input outpoints, input sequences, and outputs. Input scriptSigs and input scriptWitnesses may differ. */
     371                 :             :     bool IsMalleation(const CWalletTx& tx) const;
     372                 :             : 
     373                 :             :     bool InMempool() const;
     374                 :             : 
     375                 :             :     int64_t GetTxTime() const;
     376                 :             : 
     377   [ +  +  -  +  :        6532 :     template<typename T> const T* state() const { return std::get_if<T>(&m_state); }
          -  +  -  -  +  
          +  -  +  +  +  
             +  -  +  - ]
           [ #  #  #  # ]
           [ #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     378   [ -  -  -  -  :          13 :     template<typename T> T* state() { return std::get_if<T>(&m_state); }
          -  -  -  -  -  
             -  -  +  -  
           - ][ -  -  +  
          +  +  +  -  +  
          +  +  #  #  #  
                      # ]
     379                 :             : 
     380                 :             :     //! Update transaction state when attaching to a chain, filling in heights
     381                 :             :     //! of conflicted and confirmed blocks
     382                 :             :     void updateState(interfaces::Chain& chain);
     383                 :             : 
     384   [ +  +  +  -  :          28 :     bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; }
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  +  -  -  +  
           -  +  - ][ #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
           [ #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     385   [ -  -  -  + ]:          21 :     bool isMempoolConflicted() const { return !mempool_conflicts.empty(); }
     386   [ -  -  -  -  :          21 :     bool isBlockConflicted() const { return state<TxStateBlockConflicted>(); }
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  +  -  -  
           + ][ #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     387   [ -  +  -  -  :         838 :     bool isInactive() const { return state<TxStateInactive>(); }
           +  - ][ -  -  
             #  #  #  # ]
     388   [ +  +  +  -  :          13 :     bool isUnconfirmed() const { return !isAbandoned() && !isBlockConflicted() && !isMempoolConflicted() && !isConfirmed(); }
                   +  - ]
     389   [ +  +  +  +  :         106 :     bool isConfirmed() const { return state<TxStateConfirmed>(); }
           +  + ][ -  +  
          -  -  -  +  -  
           +  -  - ][ #  
          #  #  #  #  #  
             #  #  #  # ]
     390         [ +  - ]:      118038 :     const Txid& GetHash() const LIFETIMEBOUND { return GetTx()->GetHash(); }
     391         [ +  - ]:           2 :     const Wtxid& GetWitnessHash() const LIFETIMEBOUND { return GetTx()->GetWitnessHash(); }
     392         [ +  - ]:        5275 :     bool IsCoinBase() const { return GetTx()->IsCoinBase(); }
     393                 :             : 
     394         [ #  # ]:         830 :     const std::map<Wtxid, CTransactionRef>& GetTxs() const { return m_txs; }
     395                 :             : 
     396                 :             :     // Disable copying of CWalletTx objects to prevent bugs where instances get
     397                 :             :     // copied in and out of the mapWallet map, and fields are updated in the
     398                 :             :     // wrong copy.
     399                 :             :     CWalletTx(const CWalletTx&) = delete;
     400                 :             :     CWalletTx& operator=(const CWalletTx&) = delete;
     401                 :             : 
     402                 :             :     // Enable the default move constructor
     403         [ +  + ]:           6 :     CWalletTx(CWalletTx&&) = default;
     404                 :             : 
     405                 :             : private:
     406                 :      117084 :     void SetDefaults()
     407                 :             :     {
     408                 :      117084 :         nTimeReceived = 0;
     409                 :      117084 :         nTimeSmart = 0;
     410                 :      117084 :         fChangeCached = false;
     411                 :      117084 :         nChangeCached = 0;
     412                 :      117081 :         nOrderPos = -1;
     413                 :             :     }
     414                 :             : 
     415                 :           3 :     void Init()
     416                 :             :     {
     417                 :           3 :         m_txs.clear();
     418                 :           3 :         m_canonical_wtxid = Wtxid{};
     419                 :           3 :         SetDefaults();
     420                 :           3 :     }
     421                 :             : 
     422                 :             :     Wtxid m_canonical_wtxid;
     423                 :             :     std::map<Wtxid, CTransactionRef> m_txs;
     424                 :             : 
     425                 :             :     //! Set m_canonical_wtxid to the best variant under the unconfirmed rule
     426                 :             :     //! (witnessed preferred, then least weight). Ignores state.
     427                 :             :     void RecomputeCanonical();
     428                 :             : };
     429                 :             : 
     430                 :             : struct WalletTxOrderComparator {
     431                 :           2 :     bool operator()(const CWalletTx* a, const CWalletTx* b) const
     432                 :             :     {
     433   [ +  -  +  -  :           2 :         return a->nOrderPos < b->nOrderPos;
                   -  - ]
     434                 :             :     }
     435                 :             : };
     436                 :             : 
     437                 :             : class WalletTXO
     438                 :             : {
     439                 :             : private:
     440                 :             :     const CWalletTx& m_wtx;
     441                 :             :     const CTxOut& m_output;
     442                 :             : 
     443                 :             : public:
     444                 :         831 :     WalletTXO(const CWalletTx& wtx, const CTxOut& output)
     445                 :         831 :     : m_wtx(wtx),
     446                 :         831 :     m_output(output)
     447                 :             :     {
     448   [ +  -  +  -  :        1662 :         Assume(std::ranges::find(wtx.GetTx()->vout, output) != wtx.GetTx()->vout.end());
                   +  - ]
     449                 :         831 :     }
     450                 :             : 
     451   [ -  -  +  - ]:        2781 :     const CWalletTx& GetWalletTx() const { return m_wtx; }
                 [ +  - ]
     452                 :             : 
     453   [ -  -  -  -  :        2781 :     const CTxOut& GetTxOut() const { return m_output; }
                   -  + ]
     454                 :             : };
     455                 :             : } // namespace wallet
     456                 :             : 
     457                 :             : #endif // BITCOIN_WALLET_TRANSACTION_H
        

Generated by: LCOV version 2.0-1