aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Corallo <git@bluematt.me>2014-11-11 20:57:54 -0800
committerMatt Corallo <git@bluematt.me>2014-12-08 14:05:42 -0800
commit723d12c098456e7682e641076e76468a9fb0cec0 (patch)
treef50a3c3ee4baa4e0507dc1befda01ed03784d8af
parent868d041622e2f589ab4535c30ce683534b6d4f71 (diff)
Remove txn which are invalidated by coinbase maturity during reorg
-rw-r--r--src/main.cpp1
-rw-r--r--src/txmempool.cpp26
-rw-r--r--src/txmempool.h1
3 files changed, 28 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 3a2c167e80..9e1c41ada7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1895,6 +1895,7 @@ bool static DisconnectTip(CValidationState &state) {
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
mempool.remove(tx, removed, true);
}
+ mempool.removeCoinbaseSpends(pcoinsTip, pindexDelete->nHeight);
mempool.check(pcoinsTip);
// Update chainActive and related variables.
UpdateTip(pindexDelete->pprev);
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index e13f1cc350..ff04a8ad9a 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -6,6 +6,7 @@
#include "txmempool.h"
#include "clientversion.h"
+#include "main.h" // for COINBASE_MATURITY
#include "streams.h"
#include "util.h"
#include "utilmoneystr.h"
@@ -453,6 +454,31 @@ void CTxMemPool::remove(const CTransaction &tx, std::list<CTransaction>& removed
}
}
+void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight)
+{
+ // Remove transactions spending a coinbase which are now immature
+ LOCK(cs);
+ list<CTransaction> transactionsToRemove;
+ for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
+ const CTransaction& tx = it->second.GetTx();
+ BOOST_FOREACH(const CTxIn& txin, tx.vin) {
+ std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(txin.prevout.hash);
+ if (it2 != mapTx.end())
+ continue;
+ const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
+ if (fSanityCheck) assert(coins);
+ if (!coins || (coins->IsCoinBase() && nMemPoolHeight - coins->nHeight < COINBASE_MATURITY)) {
+ transactionsToRemove.push_back(tx);
+ break;
+ }
+ }
+ }
+ BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) {
+ list<CTransaction> removed;
+ remove(tx, removed, true);
+ }
+}
+
void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed)
{
// Remove transactions which depend on inputs of tx, recursively
diff --git a/src/txmempool.h b/src/txmempool.h
index d00bdd0616..f671352b58 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -113,6 +113,7 @@ public:
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry);
void remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive = false);
+ void removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight);
void removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed);
void removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
std::list<CTransaction>& conflicts);