Skip to content

Commit 8241b51

Browse files
committed
Merge #16451: Remove CMerkleTx
05b56d1 [wallet] Remove CMerkleTx serialization logic (John Newbery) 783a76f [wallet] Flatten CWalletTx class hierarchy (John Newbery) b3a9d17 [wallet] Move CMerkleTx functions into CWalletTx (John Newbery) Pull request description: CMerkleTx is only used as a base class for CWalletTx. It was previously also used for vtxPrev which was removed in 93a18a3. This PR moves all of the CMerkleTx members and logic into CWalletTx. The CMerkleTx class is kept for deserialization and serialization of old wallet files. This makes the refactor in #15931 cleaner. ACKs for top commit: laanwj: ACK 05b56d1. Looks good to me. Tree-SHA512: 3d3a0069ebb536b12a328f1261e7dc55158a71088d445ae4b4ace4142c432dc296f58c8183b1922e54a60b8cc77e9d17c3dce7478294cd68693594baacf2bab3
2 parents 39763b7 + 05b56d1 commit 8241b51

File tree

2 files changed

+72
-85
lines changed

2 files changed

+72
-85
lines changed

src/wallet/wallet.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString&
228228

229229
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
230230

231-
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
231+
const uint256 CWalletTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
232232

233233
/** @defgroup mapWallet
234234
*
@@ -4627,7 +4627,7 @@ CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
46274627
m_pre_split = false;
46284628
}
46294629

4630-
void CMerkleTx::SetMerkleBranch(const uint256& block_hash, int posInBlock)
4630+
void CWalletTx::SetMerkleBranch(const uint256& block_hash, int posInBlock)
46314631
{
46324632
// Update the tx's hashBlock
46334633
hashBlock = block_hash;
@@ -4636,15 +4636,15 @@ void CMerkleTx::SetMerkleBranch(const uint256& block_hash, int posInBlock)
46364636
nIndex = posInBlock;
46374637
}
46384638

4639-
int CMerkleTx::GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const
4639+
int CWalletTx::GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const
46404640
{
46414641
if (hashUnset())
46424642
return 0;
46434643

46444644
return locked_chain.getBlockDepth(hashBlock) * (nIndex == -1 ? -1 : 1);
46454645
}
46464646

4647-
int CMerkleTx::GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const
4647+
int CWalletTx::GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const
46484648
{
46494649
if (!IsCoinBase())
46504650
return 0;
@@ -4653,7 +4653,7 @@ int CMerkleTx::GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const
46534653
return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
46544654
}
46554655

4656-
bool CMerkleTx::IsImmatureCoinBase(interfaces::Chain::Lock& locked_chain) const
4656+
bool CWalletTx::IsImmatureCoinBase(interfaces::Chain::Lock& locked_chain) const
46574657
{
46584658
// note GetBlocksToMaturity is 0 for non-coinbase tx
46594659
return GetBlocksToMaturity(locked_chain) > 0;

src/wallet/wallet.h

Lines changed: 67 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -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.**/
368372
class CMerkleTx
369373
{
370-
private:
371-
/** Constant used in hashBlock to indicate tx has been abandoned */
372-
static const uint256 ABANDON_HASH;
373-
374374
public:
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
{
454396
private:
455397
const CWallet* pwallet;
456398

399+
/** Constant used in hashBlock to indicate tx has been abandoned */
400+
static const uint256 ABANDON_HASH;
401+
457402
public:
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

635622
class COutput

0 commit comments

Comments
 (0)