LCOV - code coverage report
Current view: top level - src/wallet - transaction.h (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 91 106 85.8 %
Date: 2021-06-29 14:35:33 Functions: 21 57 36.8 %
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: 18 22 81.8 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2021 The Bitcoin Core developers
#       2                 :            : // Distributed under the MIT software license, see the accompanying
#       3                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       4                 :            : 
#       5                 :            : #ifndef BITCOIN_WALLET_TRANSACTION_H
#       6                 :            : #define BITCOIN_WALLET_TRANSACTION_H
#       7                 :            : 
#       8                 :            : #include <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/strencodings.h>
#      15                 :            : #include <util/string.h>
#      16                 :            : 
#      17                 :            : #include <list>
#      18                 :            : #include <vector>
#      19                 :            : 
#      20                 :            : struct COutputEntry;
#      21                 :            : 
#      22                 :            : typedef std::map<std::string, std::string> mapValue_t;
#      23                 :            : 
#      24                 :            : //Get the marginal bytes of spending the specified output
#      25                 :            : int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, bool use_max_sig = false);
#      26                 :            : 
#      27                 :            : static inline void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
#      28                 :       9899 : {
#      29         [ -  + ]:       9899 :     if (!mapValue.count("n"))
#      30                 :          0 :     {
#      31                 :          0 :         nOrderPos = -1; // TODO: calculate elsewhere
#      32                 :          0 :         return;
#      33                 :          0 :     }
#      34                 :       9899 :     nOrderPos = atoi64(mapValue["n"]);
#      35                 :       9899 : }
#      36                 :            : 
#      37                 :            : static inline void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
#      38                 :     143205 : {
#      39         [ -  + ]:     143205 :     if (nOrderPos == -1)
#      40                 :          0 :         return;
#      41                 :     143205 :     mapValue["n"] = ToString(nOrderPos);
#      42                 :     143205 : }
#      43                 :            : 
#      44                 :            : /** Legacy class used for deserializing vtxPrev for backwards compatibility.
#      45                 :            :  * vtxPrev was removed in commit 93a18a3650292afbb441a47d1fa1b94aeb0164e3,
#      46                 :            :  * but old wallet.dat files may still contain vtxPrev vectors of CMerkleTxs.
#      47                 :            :  * These need to get deserialized for field alignment when deserializing
#      48                 :            :  * a CWalletTx, but the deserialized values are discarded.**/
#      49                 :            : class CMerkleTx
#      50                 :            : {
#      51                 :            : public:
#      52                 :            :     template<typename Stream>
#      53                 :            :     void Unserialize(Stream& s)
#      54                 :          0 :     {
#      55                 :          0 :         CTransactionRef tx;
#      56                 :          0 :         uint256 hashBlock;
#      57                 :          0 :         std::vector<uint256> vMerkleBranch;
#      58                 :          0 :         int nIndex;
#      59                 :            : 
#      60                 :          0 :         s >> tx >> hashBlock >> vMerkleBranch >> nIndex;
#      61                 :          0 :     }
#      62                 :            : };
#      63                 :            : 
#      64                 :            : /**
#      65                 :            :  * A transaction with a bunch of additional info that only the owner cares about.
#      66                 :            :  * It includes any unrecorded transactions needed to link it back to the block chain.
#      67                 :            :  */
#      68                 :            : class CWalletTx
#      69                 :            : {
#      70                 :            : private:
#      71                 :            :     const CWallet* const pwallet;
#      72                 :            : 
#      73                 :            :     /** Constant used in hashBlock to indicate tx has been abandoned, only used at
#      74                 :            :      * serialization/deserialization to avoid ambiguity with conflicted.
#      75                 :            :      */
#      76                 :            :     static constexpr const uint256& ABANDON_HASH = uint256::ONE;
#      77                 :            : 
#      78                 :            : public:
#      79                 :            :     /**
#      80                 :            :      * Key/value map with information about the transaction.
#      81                 :            :      *
#      82                 :            :      * The following keys can be read and written through the map and are
#      83                 :            :      * serialized in the wallet database:
#      84                 :            :      *
#      85                 :            :      *     "comment", "to"   - comment strings provided to sendtoaddress,
#      86                 :            :      *                         and sendmany wallet RPCs
#      87                 :            :      *     "replaces_txid"   - txid (as HexStr) of transaction replaced by
#      88                 :            :      *                         bumpfee on transaction created by bumpfee
#      89                 :            :      *     "replaced_by_txid" - txid (as HexStr) of transaction created by
#      90                 :            :      *                         bumpfee on transaction replaced by bumpfee
#      91                 :            :      *     "from", "message" - obsolete fields that could be set in UI prior to
#      92                 :            :      *                         2011 (removed in commit 4d9b223)
#      93                 :            :      *
#      94                 :            :      * The following keys are serialized in the wallet database, but shouldn't
#      95                 :            :      * be read or written through the map (they will be temporarily added and
#      96                 :            :      * removed from the map during serialization):
#      97                 :            :      *
#      98                 :            :      *     "fromaccount"     - serialized strFromAccount value
#      99                 :            :      *     "n"               - serialized nOrderPos value
#     100                 :            :      *     "timesmart"       - serialized nTimeSmart value
#     101                 :            :      *     "spent"           - serialized vfSpent value that existed prior to
#     102                 :            :      *                         2014 (removed in commit 93a18a3)
#     103                 :            :      */
#     104                 :            :     mapValue_t mapValue;
#     105                 :            :     std::vector<std::pair<std::string, std::string> > vOrderForm;
#     106                 :            :     unsigned int fTimeReceivedIsTxTime;
#     107                 :            :     unsigned int nTimeReceived; //!< time received by this node
#     108                 :            :     /**
#     109                 :            :      * Stable timestamp that never changes, and reflects the order a transaction
#     110                 :            :      * was added to the wallet. Timestamp is based on the block time for a
#     111                 :            :      * transaction added as part of a block, or else the time when the
#     112                 :            :      * transaction was received if it wasn't part of a block, with the timestamp
#     113                 :            :      * adjusted in both cases so timestamp order matches the order transactions
#     114                 :            :      * were added to the wallet. More details can be found in
#     115                 :            :      * CWallet::ComputeTimeSmart().
#     116                 :            :      */
#     117                 :            :     unsigned int nTimeSmart;
#     118                 :            :     /**
#     119                 :            :      * From me flag is set to 1 for transactions that were created by the wallet
#     120                 :            :      * on this bitcoin node, and set to 0 for transactions that were created
#     121                 :            :      * externally and came in through the network or sendrawtransaction RPC.
#     122                 :            :      */
#     123                 :            :     bool fFromMe;
#     124                 :            :     int64_t nOrderPos; //!< position in ordered transaction list
#     125                 :            :     std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
#     126                 :            : 
#     127                 :            :     // memory only
#     128                 :            :     enum AmountType { DEBIT, CREDIT, IMMATURE_CREDIT, AVAILABLE_CREDIT, AMOUNTTYPE_ENUM_ELEMENTS };
#     129                 :            :     CAmount GetCachableAmount(AmountType type, const isminefilter& filter, bool recalculate = false) const;
#     130                 :            :     mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS];
#     131                 :            :     /**
#     132                 :            :      * This flag is true if all m_amounts caches are empty. This is particularly
#     133                 :            :      * useful in places where MarkDirty is conditionally called and the
#     134                 :            :      * condition can be expensive and thus can be skipped if the flag is true.
#     135                 :            :      * See MarkDestinationsDirty.
#     136                 :            :      */
#     137                 :            :     mutable bool m_is_cache_empty{true};
#     138                 :            :     mutable bool fChangeCached;
#     139                 :            :     mutable bool fInMempool;
#     140                 :            :     mutable CAmount nChangeCached;
#     141                 :            : 
#     142                 :            :     CWalletTx(const CWallet* wallet, CTransactionRef arg)
#     143                 :            :         : pwallet(wallet),
#     144                 :            :           tx(std::move(arg))
#     145                 :     174831 :     {
#     146                 :     174831 :         Init();
#     147                 :     174831 :     }
#     148                 :            : 
#     149                 :            :     void Init()
#     150                 :     184730 :     {
#     151                 :     184730 :         mapValue.clear();
#     152                 :     184730 :         vOrderForm.clear();
#     153                 :     184730 :         fTimeReceivedIsTxTime = false;
#     154                 :     184730 :         nTimeReceived = 0;
#     155                 :     184730 :         nTimeSmart = 0;
#     156                 :     184730 :         fFromMe = false;
#     157                 :     184730 :         fChangeCached = false;
#     158                 :     184730 :         fInMempool = false;
#     159                 :     184730 :         nChangeCached = 0;
#     160                 :     184730 :         nOrderPos = -1;
#     161                 :     184730 :         m_confirm = Confirmation{};
#     162                 :     184730 :     }
#     163                 :            : 
#     164                 :            :     CTransactionRef tx;
#     165                 :            : 
#     166                 :            :     /** New transactions start as UNCONFIRMED. At BlockConnected,
#     167                 :            :      * they will transition to CONFIRMED. In case of reorg, at BlockDisconnected,
#     168                 :            :      * they roll back to UNCONFIRMED. If we detect a conflicting transaction at
#     169                 :            :      * block connection, we update conflicted tx and its dependencies as CONFLICTED.
#     170                 :            :      * If tx isn't confirmed and outside of mempool, the user may switch it to ABANDONED
#     171                 :            :      * by using the abandontransaction call. This last status may be override by a CONFLICTED
#     172                 :            :      * or CONFIRMED transition.
#     173                 :            :      */
#     174                 :            :     enum Status {
#     175                 :            :         UNCONFIRMED,
#     176                 :            :         CONFIRMED,
#     177                 :            :         CONFLICTED,
#     178                 :            :         ABANDONED
#     179                 :            :     };
#     180                 :            : 
#     181                 :            :     /** Confirmation includes tx status and a triplet of {block height/block hash/tx index in block}
#     182                 :            :      * at which tx has been confirmed. All three are set to 0 if tx is unconfirmed or abandoned.
#     183                 :            :      * Meaning of these fields changes with CONFLICTED state where they instead point to block hash
#     184                 :            :      * and block height of the deepest conflicting tx.
#     185                 :            :      */
#     186                 :            :     struct Confirmation {
#     187                 :            :         Status status;
#     188                 :            :         int block_height;
#     189                 :            :         uint256 hashBlock;
#     190                 :            :         int nIndex;
#     191                 :     661750 :         Confirmation(Status s = UNCONFIRMED, int b = 0, uint256 h = uint256(), int i = 0) : status(s), block_height(b), hashBlock(h), nIndex(i) {}
#     192                 :            :     };
#     193                 :            : 
#     194                 :            :     Confirmation m_confirm;
#     195                 :            : 
#     196                 :            :     template<typename Stream>
#     197                 :            :     void Serialize(Stream& s) const
#     198                 :     143205 :     {
#     199                 :     143205 :         mapValue_t mapValueCopy = mapValue;
#     200                 :            : 
#     201                 :     143205 :         mapValueCopy["fromaccount"] = "";
#     202                 :     143205 :         WriteOrderPos(nOrderPos, mapValueCopy);
#     203         [ +  - ]:     143205 :         if (nTimeSmart) {
#     204                 :     143205 :             mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
#     205                 :     143205 :         }
#     206                 :            : 
#     207                 :     143205 :         std::vector<char> dummy_vector1; //!< Used to be vMerkleBranch
#     208                 :     143205 :         std::vector<char> dummy_vector2; //!< Used to be vtxPrev
#     209                 :     143205 :         bool dummy_bool = false; //!< Used to be fSpent
#     210         [ +  + ]:     143205 :         uint256 serializedHash = isAbandoned() ? ABANDON_HASH : m_confirm.hashBlock;
#     211 [ +  + ][ +  + ]:     143205 :         int serializedIndex = isAbandoned() || isConflicted() ? -1 : m_confirm.nIndex;
#     212                 :     143205 :         s << tx << serializedHash << dummy_vector1 << serializedIndex << dummy_vector2 << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << dummy_bool;
#     213                 :     143205 :     }
#     214                 :            : 
#     215                 :            :     template<typename Stream>
#     216                 :            :     void Unserialize(Stream& s)
#     217                 :       9899 :     {
#     218                 :       9899 :         Init();
#     219                 :            : 
#     220                 :       9899 :         std::vector<uint256> dummy_vector1; //!< Used to be vMerkleBranch
#     221                 :       9899 :         std::vector<CMerkleTx> dummy_vector2; //!< Used to be vtxPrev
#     222                 :       9899 :         bool dummy_bool; //! Used to be fSpent
#     223                 :       9899 :         int serializedIndex;
#     224                 :       9899 :         s >> tx >> m_confirm.hashBlock >> dummy_vector1 >> serializedIndex >> dummy_vector2 >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> dummy_bool;
#     225                 :            : 
#     226                 :            :         /* At serialization/deserialization, an nIndex == -1 means that hashBlock refers to
#     227                 :            :          * the earliest block in the chain we know this or any in-wallet ancestor conflicts
#     228                 :            :          * with. If nIndex == -1 and hashBlock is ABANDON_HASH, it means transaction is abandoned.
#     229                 :            :          * In same context, an nIndex >= 0 refers to a confirmed transaction (if hashBlock set) or
#     230                 :            :          * unconfirmed one. Older clients interpret nIndex == -1 as unconfirmed for backward
#     231                 :            :          * compatibility (pre-commit 9ac63d6).
#     232                 :            :          */
#     233 [ +  + ][ +  + ]:       9899 :         if (serializedIndex == -1 && m_confirm.hashBlock == ABANDON_HASH) {
#     234                 :         10 :             setAbandoned();
#     235         [ +  + ]:       9889 :         } else if (serializedIndex == -1) {
#     236                 :         98 :             setConflicted();
#     237         [ +  + ]:       9791 :         } else if (!m_confirm.hashBlock.IsNull()) {
#     238                 :       9698 :             m_confirm.nIndex = serializedIndex;
#     239                 :       9698 :             setConfirmed();
#     240                 :       9698 :         }
#     241                 :            : 
#     242                 :       9899 :         ReadOrderPos(nOrderPos, mapValue);
#     243         [ +  - ]:       9899 :         nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
#     244                 :            : 
#     245                 :       9899 :         mapValue.erase("fromaccount");
#     246                 :       9899 :         mapValue.erase("spent");
#     247                 :       9899 :         mapValue.erase("n");
#     248                 :       9899 :         mapValue.erase("timesmart");
#     249                 :       9899 :     }
#     250                 :            : 
#     251                 :            :     void SetTx(CTransactionRef arg)
#     252                 :          0 :     {
#     253                 :          0 :         tx = std::move(arg);
#     254                 :          0 :     }
#     255                 :            : 
#     256                 :            :     //! make sure balances are recalculated
#     257                 :            :     void MarkDirty()
#     258                 :     230594 :     {
#     259                 :     230594 :         m_amounts[DEBIT].Reset();
#     260                 :     230594 :         m_amounts[CREDIT].Reset();
#     261                 :     230594 :         m_amounts[IMMATURE_CREDIT].Reset();
#     262                 :     230594 :         m_amounts[AVAILABLE_CREDIT].Reset();
#     263                 :     230594 :         fChangeCached = false;
#     264                 :     230594 :         m_is_cache_empty = true;
#     265                 :     230594 :     }
#     266                 :            : 
#     267                 :            :     //! filter decides which addresses will count towards the debit
#     268                 :            :     CAmount GetDebit(const isminefilter& filter) const;
#     269                 :            :     CAmount GetCredit(const isminefilter& filter) const;
#     270                 :            :     CAmount GetImmatureCredit(bool fUseCache = true) const;
#     271                 :            :     // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
#     272                 :            :     // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The
#     273                 :            :     // annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid
#     274                 :            :     // having to resolve the issue of member access into incomplete type CWallet.
#     275                 :            :     CAmount GetAvailableCredit(bool fUseCache = true, const isminefilter& filter = ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS;
#     276                 :            :     CAmount GetImmatureWatchOnlyCredit(const bool fUseCache = true) const;
#     277                 :            :     CAmount GetChange() const;
#     278                 :            : 
#     279                 :            :     /** Get the marginal bytes if spending the specified output from this transaction */
#     280                 :            :     int GetSpendSize(unsigned int out, bool use_max_sig = false) const
#     281                 :     511555 :     {
#     282                 :     511555 :         return CalculateMaximumSignedInputSize(tx->vout[out], pwallet, use_max_sig);
#     283                 :     511555 :     }
#     284                 :            : 
#     285                 :            :     void GetAmounts(std::list<COutputEntry>& listReceived,
#     286                 :            :                     std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter) const;
#     287                 :            : 
#     288                 :            :     bool IsFromMe(const isminefilter& filter) const
#     289                 :    1894978 :     {
#     290                 :    1894978 :         return (GetDebit(filter) > 0);
#     291                 :    1894978 :     }
#     292                 :            : 
#     293                 :            :     /** True if only scriptSigs are different */
#     294                 :            :     bool IsEquivalentTo(const CWalletTx& tx) const;
#     295                 :            : 
#     296                 :            :     bool InMempool() const;
#     297                 :            :     bool IsTrusted() const;
#     298                 :            : 
#     299                 :            :     int64_t GetTxTime() const;
#     300                 :            : 
#     301                 :            :     /** Pass this transaction to node for mempool insertion and relay to peers if flag set to true */
#     302                 :            :     bool SubmitMemoryPoolAndRelay(std::string& err_string, bool relay);
#     303                 :            : 
#     304                 :            :     // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
#     305                 :            :     // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation
#     306                 :            :     // "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid having to
#     307                 :            :     // resolve the issue of member access into incomplete type CWallet. Note
#     308                 :            :     // that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)"
#     309                 :            :     // in place.
#     310                 :            :     std::set<uint256> GetConflicts() const NO_THREAD_SAFETY_ANALYSIS;
#     311                 :            : 
#     312                 :            :     /**
#     313                 :            :      * Return depth of transaction in blockchain:
#     314                 :            :      * <0  : conflicts with a transaction this deep in the blockchain
#     315                 :            :      *  0  : in memory pool, waiting to be included in a block
#     316                 :            :      * >=1 : this many blocks deep in the main chain
#     317                 :            :      */
#     318                 :            :     // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
#     319                 :            :     // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation
#     320                 :            :     // "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid having to
#     321                 :            :     // resolve the issue of member access into incomplete type CWallet. Note
#     322                 :            :     // that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)"
#     323                 :            :     // in place.
#     324                 :            :     int GetDepthInMainChain() const NO_THREAD_SAFETY_ANALYSIS;
#     325                 :      62754 :     bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
#     326                 :            : 
#     327                 :            :     /**
#     328                 :            :      * @return number of blocks to maturity for this transaction:
#     329                 :            :      *  0 : is not a coinbase transaction, or is a mature coinbase transaction
#     330                 :            :      * >0 : is a coinbase transaction which matures in this many blocks
#     331                 :            :      */
#     332                 :            :     int GetBlocksToMaturity() const;
#     333                 :    4392752 :     bool isAbandoned() const { return m_confirm.status == CWalletTx::ABANDONED; }
#     334                 :            :     void setAbandoned()
#     335                 :         20 :     {
#     336                 :         20 :         m_confirm.status = CWalletTx::ABANDONED;
#     337                 :         20 :         m_confirm.hashBlock = uint256();
#     338                 :         20 :         m_confirm.block_height = 0;
#     339                 :         20 :         m_confirm.nIndex = 0;
#     340                 :         20 :     }
#     341                 :    3956663 :     bool isConflicted() const { return m_confirm.status == CWalletTx::CONFLICTED; }
#     342                 :        295 :     void setConflicted() { m_confirm.status = CWalletTx::CONFLICTED; }
#     343                 :    4539726 :     bool isUnconfirmed() const { return m_confirm.status == CWalletTx::UNCONFIRMED; }
#     344                 :        541 :     void setUnconfirmed() { m_confirm.status = CWalletTx::UNCONFIRMED; }
#     345                 :        637 :     bool isConfirmed() const { return m_confirm.status == CWalletTx::CONFIRMED; }
#     346                 :       9698 :     void setConfirmed() { m_confirm.status = CWalletTx::CONFIRMED; }
#     347                 :    2304269 :     const uint256& GetHash() const { return tx->GetHash(); }
#     348                 :    1952880 :     bool IsCoinBase() const { return tx->IsCoinBase(); }
#     349                 :            :     bool IsImmatureCoinBase() const;
#     350                 :            : 
#     351                 :            :     // Disable copying of CWalletTx objects to prevent bugs where instances get
#     352                 :            :     // copied in and out of the mapWallet map, and fields are updated in the
#     353                 :            :     // wrong copy.
#     354                 :            :     CWalletTx(CWalletTx const &) = delete;
#     355                 :            :     void operator=(CWalletTx const &x) = delete;
#     356                 :            : };
#     357                 :            : 
#     358                 :            : #endif // BITCOIN_WALLET_TRANSACTION_H

Generated by: LCOV version 1.14