LCOV - code coverage report
Current view: top level - src/wallet - transaction.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 96.7 % 61 59
Test Date: 2026-08-09 07:13:22 Functions: 100.0 % 8 8
Branches: 75.8 % 62 47

             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                 :             : #include <wallet/transaction.h>
       6                 :             : 
       7                 :             : #include <consensus/validation.h>
       8                 :             : #include <interfaces/chain.h>
       9                 :             : 
      10                 :             : using interfaces::FoundBlock;
      11                 :             : 
      12                 :             : namespace wallet {
      13                 :        2862 : bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
      14                 :             : {
      15         [ +  - ]:        2862 :         CMutableTransaction tx1 {*this->GetTx()};
      16   [ +  -  +  - ]:        2862 :         CMutableTransaction tx2 {*_tx.GetTx()};
      17         [ +  + ]:        5768 :         for (auto& txin : tx1.vin) {
      18                 :        2906 :             txin.scriptSig = CScript();
      19                 :        2906 :             txin.scriptWitness.SetNull();
      20                 :             :         }
      21         [ +  + ]:        5774 :         for (auto& txin : tx2.vin) {
      22                 :        2912 :             txin.scriptSig = CScript();
      23                 :        2912 :             txin.scriptWitness.SetNull();
      24                 :             :         }
      25   [ +  -  +  - ]:       11448 :         return CTransaction(tx1) == CTransaction(tx2);
      26                 :        5724 : }
      27                 :             : 
      28                 :      150171 : bool CWalletTx::InMempool() const
      29                 :             : {
      30         [ +  + ]:      150171 :     return state<TxStateInMempool>();
      31                 :             : }
      32                 :             : 
      33                 :      299660 : int64_t CWalletTx::GetTxTime() const
      34                 :             : {
      35                 :      299660 :     int64_t n = nTimeSmart;
      36         [ +  + ]:      299660 :     return n ? n : nTimeReceived;
      37                 :             : }
      38                 :             : 
      39                 :        8665 : void CWalletTx::updateState(interfaces::Chain& chain)
      40                 :             : {
      41                 :        8665 :     bool active;
      42                 :       17140 :     auto lookup_block = [&](const uint256& hash, int& height, TxState& state) {
      43                 :             :         // If tx block (or conflicting block) was reorged out of chain
      44                 :             :         // while the wallet was shutdown, change tx status to UNCONFIRMED
      45                 :             :         // and reset block height, hash, and index. ABANDONED tx don't have
      46                 :             :         // associated blocks and don't need to be updated. The case where a
      47                 :             :         // transaction was reorged out while online and then reconfirmed
      48                 :             :         // while offline is covered by the rescan logic.
      49   [ +  +  -  + ]:        8475 :         if (!chain.findBlock(hash, FoundBlock().inActiveChain(active).height(height)) || !active) {
      50         [ -  + ]:         362 :             state = TxStateInactive{};
      51                 :             :         }
      52                 :       17140 :     };
      53         [ +  + ]:        8665 :     if (auto* conf = state<TxStateConfirmed>()) {
      54                 :        8423 :         lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, m_state);
      55         [ +  + ]:         242 :     } else if (auto* conf = state<TxStateBlockConflicted>()) {
      56                 :          52 :         lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, m_state);
      57                 :             :     }
      58                 :             : 
      59                 :             :     // If the above downgraded a previously-confirmed witness variant back to unconfirmed,
      60                 :             :     // the canonical choice is no longer pinned by confirmation. Re-apply the least-weight rule.
      61         [ +  + ]:        8665 :     if (!isConfirmed()) RecomputeCanonical();
      62                 :        8665 : }
      63                 :             : 
      64                 :        8500 : bool CWalletTx::Update(CTransactionRef new_tx, const TxState& new_state)
      65                 :             : {
      66         [ -  + ]:        8500 :     Assert(new_tx);
      67   [ -  +  +  - ]:        8500 :     if (!Assume(GetHash() == new_tx->GetHash())) {
      68                 :             :         return false;
      69                 :             :     }
      70                 :        8500 :     bool ret = false;
      71         [ +  + ]:        8500 :     const auto& [tx_pair, inserted] = m_txs.emplace(new_tx->GetWitnessHash(), std::move(new_tx));
      72         [ +  + ]:        8500 :     if (inserted) {
      73                 :           3 :         ret = true;
      74                 :             :     }
      75         [ +  + ]:        8500 :     const auto& [wtxid, tx] = *tx_pair;
      76                 :             : 
      77         [ +  + ]:        8500 :     if (new_state.index() != m_state.index()) {
      78                 :        4368 :         m_state = new_state;
      79         [ +  + ]:        4368 :         if (state<TxStateConfirmed>()) {
      80                 :        3754 :             m_canonical_wtxid = wtxid;
      81                 :             :         }
      82                 :             :         ret = true;
      83                 :             :     } else {
      84         [ -  + ]:        4132 :         assert(TxStateSerializedIndex(m_state) == TxStateSerializedIndex(new_state));
      85         [ -  + ]:        4132 :         assert(TxStateSerializedBlockHash(m_state) == TxStateSerializedBlockHash(new_state));
      86                 :             :     }
      87                 :             : 
      88                 :             :     // While unconfirmed, derive the canonical variant from all known variants
      89         [ +  + ]:        8500 :     if (!isConfirmed()) {
      90                 :        2300 :         const Wtxid prev_canonical = m_canonical_wtxid;
      91                 :        2300 :         RecomputeCanonical();
      92         [ +  + ]:        2300 :         if (m_canonical_wtxid != prev_canonical) {
      93                 :             :             ret = true;
      94                 :             :         }
      95                 :             :     }
      96                 :             : 
      97                 :             :     return ret;
      98                 :             : }
      99                 :             : 
     100                 :        2903 : void CWalletTx::RecomputeCanonical()
     101                 :             : {
     102                 :             :     // Recompute the canonical variant among the witness variants. They share
     103                 :             :     // the txid but differ in the wtxid. Prefer variant with witness data and
     104                 :             :     // the least weight.
     105         [ -  + ]:        2903 :     Assert(!m_txs.empty());
     106                 :             : 
     107                 :             :     // Returns true if 'a' should be preferred over 'b'
     108                 :        2915 :     auto is_better = [](const CTransactionRef& a, const CTransactionRef& b) {
     109                 :             :         // A witnessed variant always beats a witnessless one
     110         [ +  - ]:          12 :         if (a->HasWitness() != b->HasWitness()) return a->HasWitness();
     111                 :             :         // Otherwise the lighter one wins
     112                 :          12 :         return GetTransactionWeight(*a) < GetTransactionWeight(*b);
     113                 :             :     };
     114                 :             : 
     115                 :        2903 :     auto it = m_txs.begin();
     116                 :        2903 :     auto best_wtxid = it->first;
     117                 :        2903 :     const CTransactionRef* best = &it->second;
     118                 :        2903 :     it = std::next(it);
     119         [ +  + ]:        2915 :     for (; it != m_txs.end(); it = std::next(it)) {
     120         [ -  + ]:          12 :         if (is_better(it->second, *best)) {
     121                 :           0 :             best = &it->second;
     122                 :           0 :             best_wtxid = it->first;
     123                 :             :         }
     124                 :             :     }
     125                 :        2903 :     m_canonical_wtxid = best_wtxid;
     126                 :        2903 : }
     127                 :             : } // namespace wallet
        

Generated by: LCOV version 2.0-1