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
|