@@ -953,7 +953,18 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
953953 CAmount inChainInputValue;
954954 double dPriority = view.GetPriority (tx, chainActive.Height (), inChainInputValue);
955955
956- CTxMemPoolEntry entry (tx, nFees, GetTime (), dPriority, chainActive.Height (), pool.HasNoInputsOf (tx), inChainInputValue);
956+ // Keep track of transactions that spend a coinbase, which we re-scan
957+ // during reorgs to ensure COINBASE_MATURITY is still met.
958+ bool fSpendsCoinbase = false ;
959+ BOOST_FOREACH (const CTxIn &txin, tx.vin ) {
960+ const CCoins *coins = view.AccessCoins (txin.prevout .hash );
961+ if (coins->IsCoinBase ()) {
962+ fSpendsCoinbase = true ;
963+ break ;
964+ }
965+ }
966+
967+ CTxMemPoolEntry entry (tx, nFees, GetTime (), dPriority, chainActive.Height (), pool.HasNoInputsOf (tx), inChainInputValue, fSpendsCoinbase );
957968 unsigned int nSize = entry.GetTxSize ();
958969
959970 // Don't accept it if it can't get into a block
@@ -2310,12 +2321,11 @@ void static UpdateTip(CBlockIndex *pindexNew) {
23102321 }
23112322}
23122323
2313- /* * Disconnect chainActive's tip. You want to manually re-limit mempool size after this */
2324+ /* * Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */
23142325bool static DisconnectTip (CValidationState& state, const Consensus::Params& consensusParams)
23152326{
23162327 CBlockIndex *pindexDelete = chainActive.Tip ();
23172328 assert (pindexDelete);
2318- mempool.check (pcoinsTip);
23192329 // Read block from disk.
23202330 CBlock block;
23212331 if (!ReadBlockFromDisk (block, pindexDelete, consensusParams))
@@ -2350,8 +2360,6 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons
23502360 // UpdateTransactionsFromBlock finds descendants of any transactions in this
23512361 // block that were added back and cleans up the mempool state.
23522362 mempool.UpdateTransactionsFromBlock (vHashUpdate);
2353- mempool.removeCoinbaseSpends (pcoinsTip, pindexDelete->nHeight );
2354- mempool.check (pcoinsTip);
23552363 // Update chainActive and related variables.
23562364 UpdateTip (pindexDelete->pprev );
23572365 // Let wallets know transactions went from 1-confirmed to
@@ -2375,7 +2383,6 @@ static int64_t nTimePostConnect = 0;
23752383bool static ConnectTip (CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock)
23762384{
23772385 assert (pindexNew->pprev == chainActive.Tip ());
2378- mempool.check (pcoinsTip);
23792386 // Read block from disk.
23802387 int64_t nTime1 = GetTimeMicros ();
23812388 CBlock block;
@@ -2412,7 +2419,6 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
24122419 // Remove conflicting transactions from the mempool.
24132420 list<CTransaction> txConflicted;
24142421 mempool.removeForBlock (pblock->vtx , pindexNew->nHeight , txConflicted, !IsInitialBlockDownload ());
2415- mempool.check (pcoinsTip);
24162422 // Update chainActive & related variables.
24172423 UpdateTip (pindexNew);
24182424 // Tell wallet about transactions that went from mempool
@@ -2525,46 +2531,49 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
25252531 bool fContinue = true ;
25262532 int nHeight = pindexFork ? pindexFork->nHeight : -1 ;
25272533 while (fContinue && nHeight != pindexMostWork->nHeight ) {
2528- // Don't iterate the entire list of potential improvements toward the best tip, as we likely only need
2529- // a few blocks along the way.
2530- int nTargetHeight = std::min (nHeight + 32 , pindexMostWork->nHeight );
2531- vpindexToConnect.clear ();
2532- vpindexToConnect.reserve (nTargetHeight - nHeight);
2533- CBlockIndex *pindexIter = pindexMostWork->GetAncestor (nTargetHeight);
2534- while (pindexIter && pindexIter->nHeight != nHeight) {
2535- vpindexToConnect.push_back (pindexIter);
2536- pindexIter = pindexIter->pprev ;
2537- }
2538- nHeight = nTargetHeight;
2539-
2540- // Connect new blocks.
2541- BOOST_REVERSE_FOREACH (CBlockIndex *pindexConnect, vpindexToConnect) {
2542- if (!ConnectTip (state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL )) {
2543- if (state.IsInvalid ()) {
2544- // The block violates a consensus rule.
2545- if (!state.CorruptionPossible ())
2546- InvalidChainFound (vpindexToConnect.back ());
2547- state = CValidationState ();
2548- fInvalidFound = true ;
2549- fContinue = false ;
2550- break ;
2534+ // Don't iterate the entire list of potential improvements toward the best tip, as we likely only need
2535+ // a few blocks along the way.
2536+ int nTargetHeight = std::min (nHeight + 32 , pindexMostWork->nHeight );
2537+ vpindexToConnect.clear ();
2538+ vpindexToConnect.reserve (nTargetHeight - nHeight);
2539+ CBlockIndex *pindexIter = pindexMostWork->GetAncestor (nTargetHeight);
2540+ while (pindexIter && pindexIter->nHeight != nHeight) {
2541+ vpindexToConnect.push_back (pindexIter);
2542+ pindexIter = pindexIter->pprev ;
2543+ }
2544+ nHeight = nTargetHeight;
2545+
2546+ // Connect new blocks.
2547+ BOOST_REVERSE_FOREACH (CBlockIndex *pindexConnect, vpindexToConnect) {
2548+ if (!ConnectTip (state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL )) {
2549+ if (state.IsInvalid ()) {
2550+ // The block violates a consensus rule.
2551+ if (!state.CorruptionPossible ())
2552+ InvalidChainFound (vpindexToConnect.back ());
2553+ state = CValidationState ();
2554+ fInvalidFound = true ;
2555+ fContinue = false ;
2556+ break ;
2557+ } else {
2558+ // A system error occurred (disk space, database error, ...).
2559+ return false ;
2560+ }
25512561 } else {
2552- // A system error occurred (disk space, database error, ...).
2553- return false ;
2554- }
2555- } else {
2556- PruneBlockIndexCandidates ();
2557- if (!pindexOldTip || chainActive.Tip ()->nChainWork > pindexOldTip->nChainWork ) {
2558- // We're in a better position than we were. Return temporarily to release the lock.
2559- fContinue = false ;
2560- break ;
2562+ PruneBlockIndexCandidates ();
2563+ if (!pindexOldTip || chainActive.Tip ()->nChainWork > pindexOldTip->nChainWork ) {
2564+ // We're in a better position than we were. Return temporarily to release the lock.
2565+ fContinue = false ;
2566+ break ;
2567+ }
25612568 }
25622569 }
25632570 }
2564- }
25652571
2566- if (fBlocksDisconnected )
2572+ if (fBlocksDisconnected ) {
2573+ mempool.removeForReorg (pcoinsTip, chainActive.Tip ()->nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS);
25672574 mempool.TrimToSize (GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 );
2575+ }
2576+ mempool.check (pcoinsTip);
25682577
25692578 // Callbacks/notifications for a new best chain.
25702579 if (fInvalidFound )
@@ -2672,6 +2681,7 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus
26722681 // ActivateBestChain considers blocks already in chainActive
26732682 // unconditionally valid already, so force disconnect away from it.
26742683 if (!DisconnectTip (state, consensusParams)) {
2684+ mempool.removeForReorg (pcoinsTip, chainActive.Tip ()->nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS);
26752685 return false ;
26762686 }
26772687 }
@@ -2689,6 +2699,7 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus
26892699 }
26902700
26912701 InvalidChainFound (pindex);
2702+ mempool.removeForReorg (pcoinsTip, chainActive.Tip ()->nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS);
26922703 return true ;
26932704}
26942705
0 commit comments