@@ -364,82 +364,24 @@ struct COutputEntry
364364 int vout;
365365};
366366
367- /* * A transaction with a merkle branch linking it to the block chain. */
367+ /* * Legacy class used for deserializing vtxPrev for backwards compatibility.
368+ * vtxPrev was removed in commit 93a18a3650292afbb441a47d1fa1b94aeb0164e3,
369+ * but old wallet.dat files may still contain vtxPrev vectors of CMerkleTxs.
370+ * These need to get deserialized for field alignment when deserializing
371+ * a CWalletTx, but the deserialized values are discarded.**/
368372class CMerkleTx
369373{
370- private:
371- /* * Constant used in hashBlock to indicate tx has been abandoned */
372- static const uint256 ABANDON_HASH;
373-
374374public:
375- CTransactionRef tx;
376- uint256 hashBlock;
377-
378- /* An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest
379- * block in the chain we know this or any in-wallet dependency conflicts
380- * with. Older clients interpret nIndex == -1 as unconfirmed for backward
381- * compatibility.
382- */
383- int nIndex;
384-
385- CMerkleTx ()
386- {
387- SetTx (MakeTransactionRef ());
388- Init ();
389- }
390-
391- explicit CMerkleTx (CTransactionRef arg)
392- {
393- SetTx (std::move (arg));
394- Init ();
395- }
396-
397- void Init ()
398- {
399- hashBlock = uint256 ();
400- nIndex = -1 ;
401- }
402-
403- void SetTx (CTransactionRef arg)
375+ template <typename Stream>
376+ void Unserialize (Stream& s)
404377 {
405- tx = std::move (arg);
406- }
378+ CTransactionRef tx;
379+ uint256 hashBlock;
380+ std::vector<uint256> vMerkleBranch;
381+ int nIndex;
407382
408- ADD_SERIALIZE_METHODS;
409-
410- template <typename Stream, typename Operation>
411- inline void SerializationOp (Stream& s, Operation ser_action) {
412- std::vector<uint256> vMerkleBranch; // For compatibility with older versions.
413- READWRITE (tx);
414- READWRITE (hashBlock);
415- READWRITE (vMerkleBranch);
416- READWRITE (nIndex);
383+ s >> tx >> hashBlock >> vMerkleBranch >> nIndex;
417384 }
418-
419- void SetMerkleBranch (const uint256& block_hash, int posInBlock);
420-
421- /* *
422- * Return depth of transaction in blockchain:
423- * <0 : conflicts with a transaction this deep in the blockchain
424- * 0 : in memory pool, waiting to be included in a block
425- * >=1 : this many blocks deep in the main chain
426- */
427- int GetDepthInMainChain (interfaces::Chain::Lock& locked_chain) const ;
428- bool IsInMainChain (interfaces::Chain::Lock& locked_chain) const { return GetDepthInMainChain (locked_chain) > 0 ; }
429-
430- /* *
431- * @return number of blocks to maturity for this transaction:
432- * 0 : is not a coinbase transaction, or is a mature coinbase transaction
433- * >0 : is a coinbase transaction which matures in this many blocks
434- */
435- int GetBlocksToMaturity (interfaces::Chain::Lock& locked_chain) const ;
436- bool hashUnset () const { return (hashBlock.IsNull () || hashBlock == ABANDON_HASH); }
437- bool isAbandoned () const { return (hashBlock == ABANDON_HASH); }
438- void setAbandoned () { hashBlock = ABANDON_HASH; }
439-
440- const uint256& GetHash () const { return tx->GetHash (); }
441- bool IsCoinBase () const { return tx->IsCoinBase (); }
442- bool IsImmatureCoinBase (interfaces::Chain::Lock& locked_chain) const ;
443385};
444386
445387// Get the marginal bytes of spending the specified output
@@ -449,11 +391,14 @@ int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet,
449391 * A transaction with a bunch of additional info that only the owner cares about.
450392 * It includes any unrecorded transactions needed to link it back to the block chain.
451393 */
452- class CWalletTx : public CMerkleTx
394+ class CWalletTx
453395{
454396private:
455397 const CWallet* pwallet;
456398
399+ /* * Constant used in hashBlock to indicate tx has been abandoned */
400+ static const uint256 ABANDON_HASH;
401+
457402public:
458403 /* *
459404 * Key/value map with information about the transaction.
@@ -511,7 +456,10 @@ class CWalletTx : public CMerkleTx
511456 mutable bool fInMempool ;
512457 mutable CAmount nChangeCached;
513458
514- CWalletTx (const CWallet* pwalletIn, CTransactionRef arg) : CMerkleTx(std::move(arg))
459+ CWalletTx (const CWallet* pwalletIn, CTransactionRef arg)
460+ : tx(std::move(arg)),
461+ hashBlock (uint256()),
462+ nIndex(-1 )
515463 {
516464 Init (pwalletIn);
517465 }
@@ -531,10 +479,18 @@ class CWalletTx : public CMerkleTx
531479 nOrderPos = -1 ;
532480 }
533481
482+ CTransactionRef tx;
483+ uint256 hashBlock;
484+ /* An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest
485+ * block in the chain we know this or any in-wallet dependency conflicts
486+ * with. Older clients interpret nIndex == -1 as unconfirmed for backward
487+ * compatibility.
488+ */
489+ int nIndex;
490+
534491 template <typename Stream>
535492 void Serialize (Stream& s) const
536493 {
537- char fSpent = false ;
538494 mapValue_t mapValueCopy = mapValue;
539495
540496 mapValueCopy[" fromaccount" ] = " " ;
@@ -543,20 +499,21 @@ class CWalletTx : public CMerkleTx
543499 mapValueCopy[" timesmart" ] = strprintf (" %u" , nTimeSmart);
544500 }
545501
546- s << static_cast <const CMerkleTx&>(*this );
547- std::vector<CMerkleTx> vUnused; // !< Used to be vtxPrev
548- s << vUnused << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << fSpent ;
502+ std::vector<char > dummy_vector1; // !< Used to be vMerkleBranch
503+ std::vector<char > dummy_vector2; // !< Used to be vtxPrev
504+ char dummy_char = false ; // !< Used to be fSpent
505+ s << tx << hashBlock << dummy_vector1 << nIndex << dummy_vector2 << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << dummy_char;
549506 }
550507
551508 template <typename Stream>
552509 void Unserialize (Stream& s)
553510 {
554511 Init (nullptr );
555- char fSpent ;
556512
557- s >> static_cast <CMerkleTx&>(*this );
558- std::vector<CMerkleTx> vUnused; // !< Used to be vtxPrev
559- s >> vUnused >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> fSpent ;
513+ std::vector<uint256> dummy_vector1; // !< Used to be vMerkleBranch
514+ std::vector<CMerkleTx> dummy_vector2; // !< Used to be vtxPrev
515+ char dummy_char; // ! Used to be fSpent
516+ s >> tx >> hashBlock >> dummy_vector1 >> nIndex >> dummy_vector2 >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> dummy_char;
560517
561518 ReadOrderPos (nOrderPos, mapValue);
562519 nTimeSmart = mapValue.count (" timesmart" ) ? (unsigned int )atoi64 (mapValue[" timesmart" ]) : 0 ;
@@ -567,6 +524,11 @@ class CWalletTx : public CMerkleTx
567524 mapValue.erase (" timesmart" );
568525 }
569526
527+ void SetTx (CTransactionRef arg)
528+ {
529+ tx = std::move (arg);
530+ }
531+
570532 // ! make sure balances are recalculated
571533 void MarkDirty ()
572534 {
@@ -630,6 +592,31 @@ class CWalletTx : public CMerkleTx
630592 // that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)"
631593 // in place.
632594 std::set<uint256> GetConflicts () const NO_THREAD_SAFETY_ANALYSIS;
595+
596+ void SetMerkleBranch (const uint256& block_hash, int posInBlock);
597+
598+ /* *
599+ * Return depth of transaction in blockchain:
600+ * <0 : conflicts with a transaction this deep in the blockchain
601+ * 0 : in memory pool, waiting to be included in a block
602+ * >=1 : this many blocks deep in the main chain
603+ */
604+ int GetDepthInMainChain (interfaces::Chain::Lock& locked_chain) const ;
605+ bool IsInMainChain (interfaces::Chain::Lock& locked_chain) const { return GetDepthInMainChain (locked_chain) > 0 ; }
606+
607+ /* *
608+ * @return number of blocks to maturity for this transaction:
609+ * 0 : is not a coinbase transaction, or is a mature coinbase transaction
610+ * >0 : is a coinbase transaction which matures in this many blocks
611+ */
612+ int GetBlocksToMaturity (interfaces::Chain::Lock& locked_chain) const ;
613+ bool hashUnset () const { return (hashBlock.IsNull () || hashBlock == ABANDON_HASH); }
614+ bool isAbandoned () const { return (hashBlock == ABANDON_HASH); }
615+ void setAbandoned () { hashBlock = ABANDON_HASH; }
616+
617+ const uint256& GetHash () const { return tx->GetHash (); }
618+ bool IsCoinBase () const { return tx->IsCoinBase (); }
619+ bool IsImmatureCoinBase (interfaces::Chain::Lock& locked_chain) const ;
633620};
634621
635622class COutput
0 commit comments