Skip to content

Commit baaf905

Browse files
committed
squash: introduce transactionutxohasher
1 parent c49dc4e commit baaf905

File tree

5 files changed

+64
-28
lines changed

5 files changed

+64
-28
lines changed

divi/src/BlockMemoryPoolTransactionCollector.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ std::vector<PrioritizedTransactionData> BlockMemoryPoolTransactionCollector::Pri
289289
mempool is not allowed in a time window "around" the fork, so that
290290
this should be good enough. */
291291
const ActivationState as(chainActive.Tip());
292-
const bool segwitLight = as.IsActive(Fork::SegwitLight);
292+
const TransactionUtxoHasher utxoHasher(as);
293293

294294
uint64_t nBlockSize = 1000;
295295
int nBlockSigOps = 100;
@@ -345,16 +345,15 @@ std::vector<PrioritizedTransactionData> BlockMemoryPoolTransactionCollector::Pri
345345
nBlockSigOps += nTxSigOps;
346346

347347
CTxUndo txundo;
348-
UpdateCoins(tx, view, txundo, as, nHeight);
348+
UpdateCoins(tx, view, txundo, utxoHasher, nHeight);
349349

350350
if (fPrintPriority) {
351351
LogPrintf("priority %.1f fee %s txid %s\n",
352352
dPriority, feeRate.ToString(), tx.GetHash().ToString());
353353
}
354354

355355
// Add transactions that depend on this one to the priority queue
356-
const uint256 outpointHash = (segwitLight ? tx.GetBareTxid() : tx.GetHash());
357-
AddDependingTransactionsToPriorityQueue(dependentTransactions, outpointHash, vecPriority, comparer);
356+
AddDependingTransactionsToPriorityQueue(dependentTransactions, utxoHasher.GetUtxoHash(tx), vecPriority, comparer);
358357
}
359358

360359
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);

divi/src/UtxoCheckingAndUpdating.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@
1414

1515
extern BlockMap mapBlockIndex;
1616

17+
uint256 TransactionUtxoHasher::GetUtxoHash(const CTransaction& tx) const
18+
{
19+
return tx.GetHash();
20+
}
21+
1722
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo& txundo,
18-
const ActivationState& as, const int nHeight)
23+
const TransactionUtxoHasher& hasher, const int nHeight)
1924
{
2025
// mark inputs spent
2126
if (!tx.IsCoinBase() ) {
@@ -28,9 +33,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo& txund
2833
}
2934

3035
// add outputs
31-
const uint256 outputHash = (as.IsActive(Fork::SegwitLight)
32-
? tx.GetBareTxid() : tx.GetHash());
33-
inputs.ModifyCoins(outputHash)->FromTx(tx, nHeight);
36+
inputs.ModifyCoins(hasher.GetUtxoHash(tx))->FromTx(tx, nHeight);
3437
}
3538

3639
bool CheckInputs(

divi/src/UtxoCheckingAndUpdating.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,33 @@ class CTransaction;
88
class CValidationState;
99
class CCoinsViewCache;
1010
class CTxUndo;
11-
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo& txundo, const ActivationState& as, int nHeight);
11+
class uint256;
12+
13+
/** Instances of this class translate transactions into the hashes that
14+
* will be used to refer to the UTXOs their outputs create. Initially
15+
* these are just the txid (as also with upstream Bitcoin), but for
16+
* segwit-light, they are changed to the bare txid.
17+
*
18+
* This class abstracts away the segwit-light fork and its activation
19+
* from the places that need to refer to / update UTXOs.
20+
*
21+
* For unit tests, this class can be subclassed and mocked. */
22+
class TransactionUtxoHasher
23+
{
24+
25+
public:
26+
27+
TransactionUtxoHasher() = default;
28+
virtual ~TransactionUtxoHasher() = default;
29+
30+
TransactionUtxoHasher(const TransactionUtxoHasher&) = delete;
31+
void operator=(const TransactionUtxoHasher&) = delete;
32+
33+
virtual uint256 GetUtxoHash(const CTransaction& tx) const;
34+
35+
};
36+
37+
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo& txundo, const TransactionUtxoHasher& hasher, int nHeight);
1238
bool CheckInputs(
1339
const CTransaction& tx,
1440
CValidationState& state,
@@ -17,4 +43,5 @@ bool CheckInputs(
1743
unsigned int flags,
1844
bool cacheStore,
1945
std::vector<CScriptCheck>* pvChecks = nullptr);
46+
2047
#endif// UTXO_CHECKING_AND_UPDATING_H

divi/src/main.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
13731373
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
13741374

13751375
const ActivationState as(pindex);
1376+
const TransactionUtxoHasher utxoHasher;
13761377

13771378
// undo transactions in reverse order
13781379
for (int i = block.vtx.size() - 1; i >= 0; i--) {
@@ -1416,11 +1417,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
14161417
// have outputs available even in the block itself, so we handle that case
14171418
// specially with outsEmpty.
14181419
{
1419-
const uint256 outputHash = (as.IsActive(Fork::SegwitLight)
1420-
? tx.GetBareTxid() : tx.GetHash());
1421-
14221420
CCoins outsEmpty;
1423-
CCoinsModifier outs = view.ModifyCoins(outputHash);
1421+
CCoinsModifier outs = view.ModifyCoins(utxoHasher.GetUtxoHash(tx));
14241422
outs->ClearUnspendable();
14251423

14261424
CCoins outsBlock(tx, pindex->nHeight);
@@ -1621,6 +1619,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
16211619
unsigned int nMaxBlockSigOps = MAX_BLOCK_SIGOPS_CURRENT;
16221620

16231621
const ActivationState as(pindex);
1622+
const TransactionUtxoHasher utxoHasher;
16241623
static const CChainParams& chainParameters = Params();
16251624
static const SuperblockSubsidyContainer subsidiesContainer(chainParameters);
16261625
static const BlockIncentivesPopulator incentives(
@@ -1747,7 +1746,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
17471746
if (i > 0) {
17481747
blockundo.vtxundo.push_back(CTxUndo());
17491748
}
1750-
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), as, pindex->nHeight);
1749+
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), utxoHasher, pindex->nHeight);
17511750

17521751
vPos.push_back(std::make_pair(tx.GetHash(), pos));
17531752
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
@@ -3276,6 +3275,7 @@ bool static LoadBlockIndexDB(string& strError)
32763275
return false;
32773276
}
32783277
const ActivationState as(block);
3278+
const TransactionUtxoHasher utxoHasher;
32793279

32803280
std::vector<CTxUndo> vtxundo;
32813281
vtxundo.reserve(block.vtx.size() - 1);
@@ -3285,7 +3285,7 @@ bool static LoadBlockIndexDB(string& strError)
32853285
CTxUndo undoDummy;
32863286
if (i > 0)
32873287
vtxundo.push_back(CTxUndo());
3288-
UpdateCoins(block.vtx[i], view, i == 0 ? undoDummy : vtxundo.back(), as, pindex->nHeight);
3288+
UpdateCoins(block.vtx[i], view, i == 0 ? undoDummy : vtxundo.back(), utxoHasher, pindex->nHeight);
32893289
view.SetBestBlock(hashBlock);
32903290
}
32913291

divi/src/txmempool.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ void CTxMemPool::remove(const CTransaction& origTx, std::list<CTransaction>& rem
572572
{
573573
LOCK(cs);
574574
const ActivationState as(chainActive.Tip());
575-
const bool segwitLight = as.IsActive(Fork::SegwitLight);
575+
const TransactionUtxoHasher utxoHasher;
576576
std::deque<uint256> txToRemove;
577577
txToRemove.push_back(origTx.GetHash());
578578
if (fRecursive && !mapTx.count(origTx.GetHash())) {
@@ -581,7 +581,7 @@ void CTxMemPool::remove(const CTransaction& origTx, std::list<CTransaction>& rem
581581
// happen during chain re-orgs if origTx isn't re-accepted into
582582
// the mempool for any reason.
583583
for (unsigned int i = 0; i < origTx.vout.size(); i++) {
584-
auto it = mapNextTx.find(COutPoint(segwitLight ? origTx.GetBareTxid() : origTx.GetHash(), i));
584+
auto it = mapNextTx.find(COutPoint(utxoHasher.GetUtxoHash(origTx), i));
585585
if (it == mapNextTx.end())
586586
continue;
587587
txToRemove.push_back(it->second.ptx->GetHash());
@@ -595,7 +595,7 @@ void CTxMemPool::remove(const CTransaction& origTx, std::list<CTransaction>& rem
595595
const CTransaction& tx = mapTx[hash].GetTx();
596596
if (fRecursive) {
597597
for (unsigned int i = 0; i < tx.vout.size(); i++) {
598-
auto it = mapNextTx.find(COutPoint(segwitLight ? tx.GetBareTxid() : tx.GetHash(), i));
598+
auto it = mapNextTx.find(COutPoint(utxoHasher.GetUtxoHash(tx), i));
599599
if (it == mapNextTx.end())
600600
continue;
601601
txToRemove.push_back(it->second.ptx->GetHash());
@@ -698,6 +698,7 @@ void CTxMemPool::check(const CCoinsViewCache* pcoins) const
698698
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
699699

700700
const ActivationState as(chainActive.Tip());
701+
const TransactionUtxoHasher utxoHasher;
701702

702703
LOCK(cs);
703704
list<const CTxMemPoolEntry*> waitingOnDependants;
@@ -729,7 +730,7 @@ void CTxMemPool::check(const CCoinsViewCache* pcoins) const
729730
CValidationState state;
730731
CTxUndo undo;
731732
assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, NULL));
732-
UpdateCoins(tx, mempoolDuplicate, undo, as, 1000000);
733+
UpdateCoins(tx, mempoolDuplicate, undo, utxoHasher, 1000000);
733734
}
734735
}
735736
unsigned int stepsSinceLastRemove = 0;
@@ -744,7 +745,7 @@ void CTxMemPool::check(const CCoinsViewCache* pcoins) const
744745
} else {
745746
assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, NULL));
746747
CTxUndo undo;
747-
UpdateCoins(entry->GetTx(), mempoolDuplicate, undo, as, 1000000);
748+
UpdateCoins(entry->GetTx(), mempoolDuplicate, undo, utxoHasher, 1000000);
748749
stepsSinceLastRemove = 0;
749750
}
750751
}
@@ -796,9 +797,18 @@ bool CTxMemPool::lookupOutpoint(const uint256& hash, CTransaction& result) const
796797
mempool is not allowed in a time window "around" the fork, so that
797798
this should be good enough. */
798799
const ActivationState as(chainActive.Tip());
799-
return as.IsActive(Fork::SegwitLight)
800-
? lookupBareTxid(hash, result)
801-
: lookup(hash, result);
800+
const TransactionUtxoHasher utxoHasher;
801+
802+
/* The TransactionUtxoHasher can only tell us the txid to use once we
803+
know the transaction already. Thus we check both txid and bare txid
804+
in our index; if one of them matches, we then cross-check with the
805+
then-known transaction that it actually should hash to that UTXO. */
806+
if (lookup(hash, result) && utxoHasher.GetUtxoHash(result) == hash)
807+
return true;
808+
if (lookupBareTxid(hash, result) && utxoHasher.GetUtxoHash(result) == hash)
809+
return true;
810+
811+
return false;
802812
}
803813

804814
CFeeRate CTxMemPool::estimateFee(int nBlocks) const
@@ -889,11 +899,8 @@ bool CCoinsViewMemPool::GetCoins(const uint256& txid, CCoins& coins) const
889899

890900
bool CCoinsViewMemPool::HaveCoins(const uint256& txid) const
891901
{
892-
const ActivationState as(chainActive.Tip());
893-
const bool segwitLight = as.IsActive(Fork::SegwitLight);
894-
if (segwitLight && mempool.existsBareTxid(txid))
895-
return true;
896-
if (!segwitLight && mempool.exists(txid))
902+
CTransaction dummy;
903+
if (mempool.lookupOutpoint(txid, dummy))
897904
return true;
898905

899906
return base->HaveCoins(txid);

0 commit comments

Comments
 (0)