LCOV - code coverage report
Current view: top level - src/wallet - transaction.h (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 96 109 88.1 %
Date: 2022-04-21 14:51:19 Functions: 50 130 38.5 %
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: 39 48 81.2 %

           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                 :            : #ifndef BITCOIN_WALLET_TRANSACTION_H
#       6                 :            : #define BITCOIN_WALLET_TRANSACTION_H
#       7                 :            : 
#       8                 :            : #include <consensus/amount.h>
#       9                 :            : #include <primitives/transaction.h>
#      10                 :            : #include <serialize.h>
#      11                 :            : #include <wallet/ismine.h>
#      12                 :            : #include <threadsafety.h>
#      13                 :            : #include <tinyformat.h>
#      14                 :            : #include <util/overloaded.h>
#      15                 :            : #include <util/strencodings.h>
#      16                 :            : #include <util/string.h>
#      17                 :            : 
#      18                 :            : #include <list>
#      19                 :            : #include <variant>
#      20                 :            : #include <vector>
#      21                 :            : 
#      22                 :            : namespace wallet {
#      23                 :            : //! State of transaction confirmed in a block.
#      24                 :            : struct TxStateConfirmed {
#      25                 :            :     uint256 confirmed_block_hash;
#      26                 :            :     int confirmed_block_height;
#      27                 :            :     int position_in_block;
#      28                 :            : 
#      29                 :     187167 :     explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
#      30                 :            : };
#      31                 :            : 
#      32                 :            : //! State of transaction added to mempool.
#      33                 :            : struct TxStateInMempool {
#      34                 :            : };
#      35                 :            : 
#      36                 :            : //! State of rejected transaction that conflicts with a confirmed block.
#      37                 :            : struct TxStateConflicted {
#      38                 :            :     uint256 conflicting_block_hash;
#      39                 :            :     int conflicting_block_height;
#      40                 :            : 
#      41                 :        308 :     explicit TxStateConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
#      42                 :            : };
#      43                 :            : 
#      44                 :            : //! State of transaction not confirmed or conflicting with a known block and
#      45                 :            : //! not in the mempool. May conflict with the mempool, or with an unknown block,
#      46                 :            : //! or be abandoned, never broadcast, or rejected from the mempool for another
#      47                 :            : //! reason.
#      48                 :            : struct TxStateInactive {
#      49                 :            :     bool abandoned;
#      50                 :            : 
#      51                 :     124712 :     explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
#      52                 :            : };
#      53                 :            : 
#      54                 :            : //! State of transaction loaded in an unrecognized state with unexpected hash or
#      55                 :            : //! index values. Treated as inactive (with serialized hash and index values
#      56                 :            : //! preserved) by default, but may enter another state if transaction is added
#      57                 :            : //! to the mempool, or confirmed, or abandoned, or found conflicting.
#      58                 :            : struct TxStateUnrecognized {
#      59                 :            :     uint256 block_hash;
#      60                 :            :     int index;
#      61                 :            : 
#      62                 :      10233 :     TxStateUnrecognized(const uint256& block_hash, int index) : block_hash(block_hash), index(index) {}
#      63                 :            : };
#      64                 :            : 
#      65                 :            : //! All possible CWalletTx states
#      66                 :            : using TxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateConflicted, TxStateInactive, TxStateUnrecognized>;
#      67                 :            : 
#      68                 :            : //! Subset of states transaction sync logic is implemented to handle.
#      69                 :            : using SyncTxState = std::variant<TxStateConfirmed, TxStateInMempool, TxStateInactive>;
#      70                 :            : 
#      71                 :            : //! Try to interpret deserialized TxStateUnrecognized data as a recognized state.
#      72                 :            : static inline TxState TxStateInterpretSerialized(TxStateUnrecognized data)
#      73                 :      10233 : {
#      74 [ +  + ][ +  + ]:      10233 :     if (data.block_hash == uint256::ZERO) {
#      75 [ +  + ][ +  - ]:         98 :         if (data.index == 0) return TxStateInactive{};
#      76 [ +  + ][ +  + ]:      10135 :     } else if (data.block_hash == uint256::ONE) {
#      77 [ +  + ][ +  - ]:         15 :         if (data.index == -1) return TxStateInactive{/*abandoned=*/true};
#      78 [ +  + ][ +  + ]:      10120 :     } else if (data.index >= 0) {
#      79                 :      10004 :         return TxStateConfirmed{data.block_hash, /*height=*/-1, data.index};
#      80 [ +  + ][ +  - ]:      10004 :     } else if (data.index == -1) {
#      81                 :        113 :         return TxStateConflicted{data.block_hash, /*height=*/-1};
#      82                 :        113 :     }
#      83                 :         11 :     return data;
#      84                 :      10233 : }
#      85                 :            : 
#      86                 :            : //! Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
#      87                 :            : static inline uint256 TxStateSerializedBlockHash(const TxState& state)
#      88                 :      81109 : {
#      89                 :      81109 :     return std::visit(util::Overloaded{
#      90 [ +  + ][ -  + ]:      81109 :         [](const TxStateInactive& inactive) { return inactive.abandoned ? uint256::ONE : uint256::ZERO; },
#                 [ +  + ]
#      91                 :      81109 :         [](const TxStateInMempool& in_mempool) { return uint256::ZERO; },
#      92                 :      81109 :         [](const TxStateConfirmed& confirmed) { return confirmed.confirmed_block_hash; },
#      93                 :      81109 :         [](const TxStateConflicted& conflicted) { return conflicted.conflicting_block_hash; },
#      94                 :      81109 :         [](const TxStateUnrecognized& unrecognized) { return unrecognized.block_hash; }
#      95                 :      81109 :     }, state);
#      96                 :      81109 : }
#      97                 :            : 
#      98                 :            : //! Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
#      99                 :            : static inline int TxStateSerializedIndex(const TxState& state)
#     100                 :      81109 : {
#     101                 :      81109 :     return std::visit(util::Overloaded{
#     102 [ +  + ][ -  + ]:      81109 :         [](const TxStateInactive& inactive) { return inactive.abandoned ? -1 : 0; },
#                 [ +  + ]
#     103                 :      81109 :         [](const TxStateInMempool& in_mempool) { return 0; },
#     104                 :      81109 :         [](const TxStateConfirmed& confirmed) { return confirmed.position_in_block; },
#     105                 :      81109 :         [](const TxStateConflicted& conflicted) { return -1; },
#     106                 :      81109 :         [](const TxStateUnrecognized& unrecognized) { return unrecognized.index; }
#     107                 :      81109 :     }, state);
#     108                 :      81109 : }
#     109                 :            : 
#     110                 :            : 
#     111                 :            : typedef std::map<std::string, std::string> mapValue_t;
#     112                 :            : 
#     113                 :            : /** Legacy class used for deserializing vtxPrev for backwards compatibility.
#     114                 :            :  * vtxPrev was removed in commit 93a18a3650292afbb441a47d1fa1b94aeb0164e3,
#     115                 :            :  * but old wallet.dat files may still contain vtxPrev vectors of CMerkleTxs.
#     116                 :            :  * These need to get deserialized for field alignment when deserializing
#     117                 :            :  * a CWalletTx, but the deserialized values are discarded.**/
#     118                 :            : class CMerkleTx
#     119                 :            : {
#     120                 :            : public:
#     121                 :            :     template<typename Stream>
#     122                 :            :     void Unserialize(Stream& s)
#     123                 :          0 :     {
#     124                 :          0 :         CTransactionRef tx;
#     125                 :          0 :         uint256 hashBlock;
#     126                 :          0 :         std::vector<uint256> vMerkleBranch;
#     127                 :          0 :         int nIndex;
#     128                 :            : 
#     129                 :          0 :         s >> tx >> hashBlock >> vMerkleBranch >> nIndex;
#     130                 :          0 :     }
#     131                 :            : };
#     132                 :            : 
#     133                 :            : /**
#     134                 :            :  * A transaction with a bunch of additional info that only the owner cares about.
#     135                 :            :  * It includes any unrecorded transactions needed to link it back to the block chain.
#     136                 :            :  */
#     137                 :            : class CWalletTx
#     138                 :            : {
#     139                 :            : public:
#     140                 :            :     /**
#     141                 :            :      * Key/value map with information about the transaction.
#     142                 :            :      *
#     143                 :            :      * The following keys can be read and written through the map and are
#     144                 :            :      * serialized in the wallet database:
#     145                 :            :      *
#     146                 :            :      *     "comment", "to"   - comment strings provided to sendtoaddress,
#     147                 :            :      *                         and sendmany wallet RPCs
#     148                 :            :      *     "replaces_txid"   - txid (as HexStr) of transaction replaced by
#     149                 :            :      *                         bumpfee on transaction created by bumpfee
#     150                 :            :      *     "replaced_by_txid" - txid (as HexStr) of transaction created by
#     151                 :            :      *                         bumpfee on transaction replaced by bumpfee
#     152                 :            :      *     "from", "message" - obsolete fields that could be set in UI prior to
#     153                 :            :      *                         2011 (removed in commit 4d9b223)
#     154                 :            :      *
#     155                 :            :      * The following keys are serialized in the wallet database, but shouldn't
#     156                 :            :      * be read or written through the map (they will be temporarily added and
#     157                 :            :      * removed from the map during serialization):
#     158                 :            :      *
#     159                 :            :      *     "fromaccount"     - serialized strFromAccount value
#     160                 :            :      *     "n"               - serialized nOrderPos value
#     161                 :            :      *     "timesmart"       - serialized nTimeSmart value
#     162                 :            :      *     "spent"           - serialized vfSpent value that existed prior to
#     163                 :            :      *                         2014 (removed in commit 93a18a3)
#     164                 :            :      */
#     165                 :            :     mapValue_t mapValue;
#     166                 :            :     std::vector<std::pair<std::string, std::string> > vOrderForm;
#     167                 :            :     unsigned int fTimeReceivedIsTxTime;
#     168                 :            :     unsigned int nTimeReceived; //!< time received by this node
#     169                 :            :     /**
#     170                 :            :      * Stable timestamp that never changes, and reflects the order a transaction
#     171                 :            :      * was added to the wallet. Timestamp is based on the block time for a
#     172                 :            :      * transaction added as part of a block, or else the time when the
#     173                 :            :      * transaction was received if it wasn't part of a block, with the timestamp
#     174                 :            :      * adjusted in both cases so timestamp order matches the order transactions
#     175                 :            :      * were added to the wallet. More details can be found in
#     176                 :            :      * CWallet::ComputeTimeSmart().
#     177                 :            :      */
#     178                 :            :     unsigned int nTimeSmart;
#     179                 :            :     /**
#     180                 :            :      * From me flag is set to 1 for transactions that were created by the wallet
#     181                 :            :      * on this bitcoin node, and set to 0 for transactions that were created
#     182                 :            :      * externally and came in through the network or sendrawtransaction RPC.
#     183                 :            :      */
#     184                 :            :     bool fFromMe;
#     185                 :            :     int64_t nOrderPos; //!< position in ordered transaction list
#     186                 :            :     std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
#     187                 :            : 
#     188                 :            :     // memory only
#     189                 :            :     enum AmountType { DEBIT, CREDIT, IMMATURE_CREDIT, AVAILABLE_CREDIT, AMOUNTTYPE_ENUM_ELEMENTS };
#     190                 :            :     mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS];
#     191                 :            :     /**
#     192                 :            :      * This flag is true if all m_amounts caches are empty. This is particularly
#     193                 :            :      * useful in places where MarkDirty is conditionally called and the
#     194                 :            :      * condition can be expensive and thus can be skipped if the flag is true.
#     195                 :            :      * See MarkDestinationsDirty.
#     196                 :            :      */
#     197                 :            :     mutable bool m_is_cache_empty{true};
#     198                 :            :     mutable bool fChangeCached;
#     199                 :            :     mutable CAmount nChangeCached;
#     200                 :            : 
#     201                 :            :     CWalletTx(CTransactionRef tx, const TxState& state) : tx(std::move(tx)), m_state(state)
#     202                 :     176426 :     {
#     203                 :     176426 :         Init();
#     204                 :     176426 :     }
#     205                 :            : 
#     206                 :            :     void Init()
#     207                 :     186634 :     {
#     208                 :     186634 :         mapValue.clear();
#     209                 :     186634 :         vOrderForm.clear();
#     210                 :     186634 :         fTimeReceivedIsTxTime = false;
#     211                 :     186634 :         nTimeReceived = 0;
#     212                 :     186634 :         nTimeSmart = 0;
#     213                 :     186634 :         fFromMe = false;
#     214                 :     186634 :         fChangeCached = false;
#     215                 :     186634 :         nChangeCached = 0;
#     216                 :     186634 :         nOrderPos = -1;
#     217                 :     186634 :     }
#     218                 :            : 
#     219                 :            :     CTransactionRef tx;
#     220                 :            :     TxState m_state;
#     221                 :            : 
#     222                 :            :     template<typename Stream>
#     223                 :            :     void Serialize(Stream& s) const
#     224                 :      32060 :     {
#     225                 :      32060 :         mapValue_t mapValueCopy = mapValue;
#     226                 :            : 
#     227                 :      32060 :         mapValueCopy["fromaccount"] = "";
#     228         [ +  - ]:      32060 :         if (nOrderPos != -1) {
#     229                 :      32060 :             mapValueCopy["n"] = ToString(nOrderPos);
#     230                 :      32060 :         }
#     231         [ +  - ]:      32060 :         if (nTimeSmart) {
#     232                 :      32060 :             mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
#     233                 :      32060 :         }
#     234                 :            : 
#     235                 :      32060 :         std::vector<uint8_t> dummy_vector1; //!< Used to be vMerkleBranch
#     236                 :      32060 :         std::vector<uint8_t> dummy_vector2; //!< Used to be vtxPrev
#     237                 :      32060 :         bool dummy_bool = false; //!< Used to be fSpent
#     238                 :      32060 :         uint256 serializedHash = TxStateSerializedBlockHash(m_state);
#     239                 :      32060 :         int serializedIndex = TxStateSerializedIndex(m_state);
#     240                 :      32060 :         s << tx << serializedHash << dummy_vector1 << serializedIndex << dummy_vector2 << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << dummy_bool;
#     241                 :      32060 :     }
#     242                 :            : 
#     243                 :            :     template<typename Stream>
#     244                 :            :     void Unserialize(Stream& s)
#     245                 :      10208 :     {
#     246                 :      10208 :         Init();
#     247                 :            : 
#     248                 :      10208 :         std::vector<uint256> dummy_vector1; //!< Used to be vMerkleBranch
#     249                 :      10208 :         std::vector<CMerkleTx> dummy_vector2; //!< Used to be vtxPrev
#     250                 :      10208 :         bool dummy_bool; //! Used to be fSpent
#     251                 :      10208 :         uint256 serialized_block_hash;
#     252                 :      10208 :         int serializedIndex;
#     253                 :      10208 :         s >> tx >> serialized_block_hash >> dummy_vector1 >> serializedIndex >> dummy_vector2 >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> dummy_bool;
#     254                 :            : 
#     255                 :      10208 :         m_state = TxStateInterpretSerialized({serialized_block_hash, serializedIndex});
#     256                 :            : 
#     257                 :      10208 :         const auto it_op = mapValue.find("n");
#     258         [ +  - ]:      10208 :         nOrderPos = (it_op != mapValue.end()) ? LocaleIndependentAtoi<int64_t>(it_op->second) : -1;
#     259                 :      10208 :         const auto it_ts = mapValue.find("timesmart");
#     260         [ +  - ]:      10208 :         nTimeSmart = (it_ts != mapValue.end()) ? static_cast<unsigned int>(LocaleIndependentAtoi<int64_t>(it_ts->second)) : 0;
#     261                 :            : 
#     262                 :      10208 :         mapValue.erase("fromaccount");
#     263                 :      10208 :         mapValue.erase("spent");
#     264                 :      10208 :         mapValue.erase("n");
#     265                 :      10208 :         mapValue.erase("timesmart");
#     266                 :      10208 :     }
#     267                 :            : 
#     268                 :            :     void SetTx(CTransactionRef arg)
#     269                 :          0 :     {
#     270                 :          0 :         tx = std::move(arg);
#     271                 :          0 :     }
#     272                 :            : 
#     273                 :            :     //! make sure balances are recalculated
#     274                 :            :     void MarkDirty()
#     275                 :     126069 :     {
#     276                 :     126069 :         m_amounts[DEBIT].Reset();
#     277                 :     126069 :         m_amounts[CREDIT].Reset();
#     278                 :     126069 :         m_amounts[IMMATURE_CREDIT].Reset();
#     279                 :     126069 :         m_amounts[AVAILABLE_CREDIT].Reset();
#     280                 :     126069 :         fChangeCached = false;
#     281                 :     126069 :         m_is_cache_empty = true;
#     282                 :     126069 :     }
#     283                 :            : 
#     284                 :            :     /** True if only scriptSigs are different */
#     285                 :            :     bool IsEquivalentTo(const CWalletTx& tx) const;
#     286                 :            : 
#     287                 :            :     bool InMempool() const;
#     288                 :            : 
#     289                 :            :     int64_t GetTxTime() const;
#     290                 :            : 
#     291                 :    5736094 :     template<typename T> const T* state() const { return std::get_if<T>(&m_state); }
#     292                 :      32564 :     template<typename T> T* state() { return std::get_if<T>(&m_state); }
#     293                 :            : 
#     294 [ +  + ][ +  + ]:     272578 :     bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; }
#     295                 :          0 :     bool isConflicted() const { return state<TxStateConflicted>(); }
#     296                 :          0 :     bool isUnconfirmed() const { return !isAbandoned() && !isConflicted() && !isConfirmed(); }
#     297                 :          0 :     bool isConfirmed() const { return state<TxStateConfirmed>(); }
#     298                 :     927078 :     const uint256& GetHash() const { return tx->GetHash(); }
#     299                 :       3846 :     const uint256& GetWitnessHash() const { return tx->GetWitnessHash(); }
#     300                 :    2065172 :     bool IsCoinBase() const { return tx->IsCoinBase(); }
#     301                 :            : 
#     302                 :            :     // Disable copying of CWalletTx objects to prevent bugs where instances get
#     303                 :            :     // copied in and out of the mapWallet map, and fields are updated in the
#     304                 :            :     // wrong copy.
#     305                 :            :     CWalletTx(CWalletTx const &) = delete;
#     306                 :            :     void operator=(CWalletTx const &x) = delete;
#     307                 :            : };
#     308                 :            : } // namespace wallet
#     309                 :            : 
#     310                 :            : #endif // BITCOIN_WALLET_TRANSACTION_H

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