Evict transactions with obsolete anchors from the mempool
This commit is contained in:
15
src/main.cpp
15
src/main.cpp
@@ -2687,7 +2687,8 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
|
|||||||
if (!ReadBlockFromDisk(block, pindexDelete))
|
if (!ReadBlockFromDisk(block, pindexDelete))
|
||||||
return AbortNode(state, "Failed to read block");
|
return AbortNode(state, "Failed to read block");
|
||||||
// Apply the block atomically to the chain state.
|
// Apply the block atomically to the chain state.
|
||||||
uint256 anchorBeforeDisconnect = pcoinsTip->GetBestAnchor(SPROUT);
|
uint256 sproutAnchorBeforeDisconnect = pcoinsTip->GetBestAnchor(SPROUT);
|
||||||
|
uint256 saplingAnchorBeforeDisconnect = pcoinsTip->GetBestAnchor(SAPLING);
|
||||||
int64_t nStart = GetTimeMicros();
|
int64_t nStart = GetTimeMicros();
|
||||||
{
|
{
|
||||||
CCoinsViewCache view(pcoinsTip);
|
CCoinsViewCache view(pcoinsTip);
|
||||||
@@ -2696,7 +2697,8 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
|
|||||||
assert(view.Flush());
|
assert(view.Flush());
|
||||||
}
|
}
|
||||||
LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
|
LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
|
||||||
uint256 anchorAfterDisconnect = pcoinsTip->GetBestAnchor(SPROUT);
|
uint256 sproutAnchorAfterDisconnect = pcoinsTip->GetBestAnchor(SPROUT);
|
||||||
|
uint256 saplingAnchorAfterDisconnect = pcoinsTip->GetBestAnchor(SAPLING);
|
||||||
// Write the chain state to disk, if necessary.
|
// Write the chain state to disk, if necessary.
|
||||||
if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
|
if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
|
||||||
return false;
|
return false;
|
||||||
@@ -2710,10 +2712,15 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
|
|||||||
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
|
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
|
||||||
mempool.remove(tx, removed, true);
|
mempool.remove(tx, removed, true);
|
||||||
}
|
}
|
||||||
if (anchorBeforeDisconnect != anchorAfterDisconnect) {
|
if (sproutAnchorBeforeDisconnect != sproutAnchorAfterDisconnect) {
|
||||||
// The anchor may not change between block disconnects,
|
// The anchor may not change between block disconnects,
|
||||||
// in which case we don't want to evict from the mempool yet!
|
// in which case we don't want to evict from the mempool yet!
|
||||||
mempool.removeWithAnchor(anchorBeforeDisconnect);
|
mempool.removeWithAnchor(sproutAnchorBeforeDisconnect, SPROUT);
|
||||||
|
}
|
||||||
|
if (saplingAnchorBeforeDisconnect != saplingAnchorAfterDisconnect) {
|
||||||
|
// The anchor may not change between block disconnects,
|
||||||
|
// in which case we don't want to evict from the mempool yet!
|
||||||
|
mempool.removeWithAnchor(saplingAnchorBeforeDisconnect, SAPLING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CTxMemPool::removeWithAnchor(const uint256 &invalidRoot)
|
void CTxMemPool::removeWithAnchor(const uint256 &invalidRoot, ShieldedType type)
|
||||||
{
|
{
|
||||||
// If a block is disconnected from the tip, and the root changed,
|
// If a block is disconnected from the tip, and the root changed,
|
||||||
// we must invalidate transactions from the mempool which spend
|
// we must invalidate transactions from the mempool which spend
|
||||||
@@ -217,11 +217,26 @@ void CTxMemPool::removeWithAnchor(const uint256 &invalidRoot)
|
|||||||
|
|
||||||
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
||||||
const CTransaction& tx = it->GetTx();
|
const CTransaction& tx = it->GetTx();
|
||||||
BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) {
|
switch (type) {
|
||||||
if (joinsplit.anchor == invalidRoot) {
|
case SPROUT:
|
||||||
transactionsToRemove.push_back(tx);
|
BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) {
|
||||||
break;
|
if (joinsplit.anchor == invalidRoot) {
|
||||||
}
|
transactionsToRemove.push_back(tx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SAPLING:
|
||||||
|
BOOST_FOREACH(const SpendDescription& spendDescription, tx.vShieldedSpend) {
|
||||||
|
if (spendDescription.anchor == invalidRoot) {
|
||||||
|
transactionsToRemove.push_back(tx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw runtime_error("Unknown shielded type " + type);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ public:
|
|||||||
|
|
||||||
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true);
|
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true);
|
||||||
void remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive = false);
|
void remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive = false);
|
||||||
void removeWithAnchor(const uint256 &invalidRoot);
|
void removeWithAnchor(const uint256 &invalidRoot, ShieldedType type);
|
||||||
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
|
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
|
||||||
void removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed);
|
void removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed);
|
||||||
void removeExpired(unsigned int nBlockHeight);
|
void removeExpired(unsigned int nBlockHeight);
|
||||||
|
|||||||
Reference in New Issue
Block a user