Skip to content

Commit 4813286

Browse files
committed
[Mempool] Remove txes spending from a disconnected root
1 parent 2173e16 commit 4813286

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

src/txmempool.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,31 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
536536
}
537537
}
538538

539+
void CTxMemPool::removeWithAnchor(const uint256& invalidRoot)
540+
{
541+
542+
// If a block is disconnected from the tip, and the root changed,
543+
// we must invalidate transactions from the mempool which spend
544+
// from that root -- almost as though they were spending coinbases
545+
// which are no longer valid to spend due to coinbase maturity.
546+
LOCK(cs);
547+
std::list<CTransaction> transactionsToRemove;
548+
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
549+
const CTransaction& tx = it->GetTx();
550+
if (!tx.IsShieldedTx()) continue;
551+
for (const auto& sd : tx.sapData->vShieldedSpend) {
552+
if (sd.anchor == invalidRoot) {
553+
transactionsToRemove.push_back(tx);
554+
break;
555+
}
556+
}
557+
}
558+
for (const CTransaction& tx : transactionsToRemove) {
559+
std::list<CTransactionRef> removed;
560+
remove(tx, removed, true);
561+
}
562+
}
563+
539564
void CTxMemPool::removeConflicts(const CTransaction& tx, std::list<CTransactionRef>& removed)
540565
{
541566
// Remove transactions which depend on inputs of tx, recursively

src/txmempool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ class CTxMemPool
479479
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool fCurrentEstimate = true);
480480
void remove(const CTransaction& tx, std::list<CTransactionRef>& removed, bool fRecursive = false);
481481
void removeForReorg(const CCoinsViewCache* pcoins, unsigned int nMemPoolHeight, int flags);
482+
void removeWithAnchor(const uint256& invalidRoot);
482483
void removeConflicts(const CTransaction& tx, std::list<CTransactionRef>& removed);
483484
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight, std::list<CTransactionRef>& conflicts, bool fCurrentEstimate = true);
484485
void clear();

src/validation.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
19591959
if (!ReadBlockFromDisk(block, pindexDelete))
19601960
return AbortNode(state, "Failed to read block");
19611961
// Apply the block atomically to the chain state.
1962+
const uint256& saplingAnchorBeforeDisconnect = pcoinsTip->GetBestAnchor();
19621963
int64_t nStart = GetTimeMicros();
19631964
{
19641965
CCoinsViewCache view(pcoinsTip);
@@ -1967,6 +1968,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
19671968
assert(view.Flush());
19681969
}
19691970
LogPrint(BCLog::BENCH, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
1971+
const uint256& saplingAnchorAfterDisconnect = pcoinsTip->GetBestAnchor();
19701972
// Write the chain state to disk, if necessary.
19711973
if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS))
19721974
return false;
@@ -1996,6 +1998,12 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
19961998
} else {
19971999
mnodeman.UncacheBlockHash(pindexDelete);
19982000
}
2001+
// Evict from mempool if the anchor changes
2002+
if (saplingAnchorBeforeDisconnect != saplingAnchorAfterDisconnect) {
2003+
// The anchor may not change between block disconnects,
2004+
// in which case we don't want to evict from the mempool yet!
2005+
mempool.removeWithAnchor(saplingAnchorBeforeDisconnect);
2006+
}
19992007
// Update chainActive and related variables.
20002008
UpdateTip(pindexDelete->pprev);
20012009
// Let wallets know transactions went from 1-confirmed to

0 commit comments

Comments
 (0)