diff --git a/src/main.cpp b/src/main.cpp index d41ae6f55a..84e446f45a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2913,7 +2913,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); // Remove conflicting transactions from the mempool. list txConflicted; - mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload()); + mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, setWithdrawsSpent, txConflicted, !IsInitialBlockDownload()); // Update chainActive & related variables. UpdateTip(pindexNew, chainparams); // Tell wallet about transactions that went from mempool diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index 033a50f94f..1999722fd5 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -554,7 +554,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) SetMockTime(42 + CTxMemPool::ROLLING_FEE_HALFLIFE); BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000); // ... we should keep the same min fee until we get a block - pool.removeForBlock(vtx, 1, conflicts); + std::set > setWithdrawsSpent; + pool.removeForBlock(vtx, 1, setWithdrawsSpent, conflicts); SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE); BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/2); // ... then feerate should drop 1/2 each halflife diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 5c902387f1..b5ef2c063f 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -47,6 +47,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) garbage.push_back('X'); CMutableTransaction tx; std::list dummyConflicted; + std::set > dummyWithdraws; tx.vin.resize(1); tx.vin[0].scriptSig = garbage; tx.vout.resize(1); @@ -81,7 +82,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) txHashes[9-h].pop_back(); } } - mpool.removeForBlock(block, ++blocknum, dummyConflicted); + mpool.removeForBlock(block, ++blocknum, dummyWithdraws, dummyConflicted); block.clear(); if (blocknum == 30) { // At this point we should need to combine 5 buckets to get enough data points @@ -125,7 +126,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) // Mine 50 more blocks with no transactions happening, estimates shouldn't change // We haven't decayed the moving average enough so we still have enough data points in every bucket while (blocknum < 250) - mpool.removeForBlock(block, ++blocknum, dummyConflicted); + mpool.removeForBlock(block, ++blocknum, dummyWithdraws, dummyConflicted); for (int i = 1; i < 10;i++) { BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee); @@ -146,7 +147,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) txHashes[j].push_back(hash); } } - mpool.removeForBlock(block, ++blocknum, dummyConflicted); + mpool.removeForBlock(block, ++blocknum, dummyWithdraws, dummyConflicted); } int answerFound; @@ -167,7 +168,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) txHashes[j].pop_back(); } } - mpool.removeForBlock(block, 265, dummyConflicted); + mpool.removeForBlock(block, 265, dummyWithdraws, dummyConflicted); block.clear(); for (int i = 1; i < 10;i++) { BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); @@ -187,7 +188,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) block.push_back(*ptx); } } - mpool.removeForBlock(block, ++blocknum, dummyConflicted); + mpool.removeForBlock(block, ++blocknum, dummyWithdraws, dummyConflicted); block.clear(); } for (int i = 1; i < 10; i++) { diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 3880d48f43..c426ec9c93 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -603,6 +603,7 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list * Called when a block is connected. Removes from mempool and updates the miner fee estimator. */ void CTxMemPool::removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, + const std::set >& setWithdrawsSpent, std::list& conflicts, bool fCurrentEstimate) { LOCK(cs); @@ -626,6 +627,16 @@ void CTxMemPool::removeForBlock(const std::vector& vtx, unsigned i removeConflicts(tx, conflicts); ClearPrioritisation(tx.GetHash()); } + for (std::set >::const_iterator it = setWithdrawsSpent.begin(); it != setWithdrawsSpent.end(); it++) { + std::map, uint256>::const_iterator it2 = mapWithdrawsSpentToTxid.find(*it); + if (it2 != mapWithdrawsSpentToTxid.end()) { + txiter txit = mapTx.find(it2->second); + assert(txit != mapTx.end()); + setEntries stage; + stage.insert(txit); + RemoveStaged(stage, true); + } + } // After the txs in the new block have been removed from the mempool, update policy estimates minerPolicyEstimator->processBlock(nBlockHeight, entries, fCurrentEstimate); lastRollingFeeUpdate = GetTime(); diff --git a/src/txmempool.h b/src/txmempool.h index 560c7183e5..23d4cc53c8 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -525,6 +525,7 @@ public: void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags); void removeConflicts(const CTransaction &tx, std::list& removed); void removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, + const std::set >& setWithdrawsSpent, std::list& conflicts, bool fCurrentEstimate = true); void clear(); void _clear(); //lock free