6
6
#include " txmempool.h"
7
7
8
8
#include " clientversion.h"
9
+ #include " main.h"
9
10
#include " streams.h"
10
11
#include " util.h"
11
12
#include " utilmoneystr.h"
@@ -426,33 +427,64 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry)
426
427
}
427
428
428
429
429
- void CTxMemPool::remove (const CTransaction &tx , std::list<CTransaction>& removed, bool fRecursive )
430
+ void CTxMemPool::remove (const CTransaction &origTx , std::list<CTransaction>& removed, bool fRecursive )
430
431
{
431
432
// Remove transaction from memory pool
432
433
{
433
434
LOCK (cs);
434
- uint256 hash = tx.GetHash ();
435
- if (fRecursive ) {
436
- for (unsigned int i = 0 ; i < tx.vout .size (); i++) {
437
- std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find (COutPoint (hash, i));
438
- if (it == mapNextTx.end ())
439
- continue ;
440
- remove (*it->second .ptx , removed, true );
441
- }
442
- }
443
- if (mapTx.count (hash))
435
+ std::deque<uint256> txToRemove;
436
+ txToRemove.push_back (origTx.GetHash ());
437
+ while (!txToRemove.empty ())
444
438
{
445
- removed.push_front (tx);
439
+ uint256 hash = txToRemove.front ();
440
+ txToRemove.pop_front ();
441
+ if (!mapTx.count (hash))
442
+ continue ;
443
+ const CTransaction& tx = mapTx[hash].GetTx ();
444
+ if (fRecursive ) {
445
+ for (unsigned int i = 0 ; i < tx.vout .size (); i++) {
446
+ std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find (COutPoint (hash, i));
447
+ if (it == mapNextTx.end ())
448
+ continue ;
449
+ txToRemove.push_back (it->second .ptx ->GetHash ());
450
+ }
451
+ }
446
452
BOOST_FOREACH (const CTxIn& txin, tx.vin )
447
453
mapNextTx.erase (txin.prevout );
448
454
455
+ removed.push_back (tx);
449
456
totalTxSize -= mapTx[hash].GetTxSize ();
450
457
mapTx.erase (hash);
451
458
nTransactionsUpdated++;
452
459
}
453
460
}
454
461
}
455
462
463
+ void CTxMemPool::removeCoinbaseSpends (const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight)
464
+ {
465
+ // Remove transactions spending a coinbase which are now immature
466
+ LOCK (cs);
467
+ list<CTransaction> transactionsToRemove;
468
+ for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin (); it != mapTx.end (); it++) {
469
+ const CTransaction& tx = it->second .GetTx ();
470
+ BOOST_FOREACH (const CTxIn& txin, tx.vin ) {
471
+ std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find (txin.prevout .hash );
472
+ if (it2 != mapTx.end ())
473
+ continue ;
474
+ const CCoins *coins = pcoins->AccessCoins (txin.prevout .hash );
475
+ if (fSanityCheck ) assert (coins);
476
+ if (!coins || (coins->IsCoinBase () && nMemPoolHeight - coins->nHeight < COINBASE_MATURITY)) {
477
+ transactionsToRemove.push_back (tx);
478
+ break ;
479
+ }
480
+ }
481
+ }
482
+ BOOST_FOREACH (const CTransaction& tx, transactionsToRemove) {
483
+ list<CTransaction> removed;
484
+ remove (tx, removed, true );
485
+ }
486
+ }
487
+
456
488
void CTxMemPool::removeConflicts (const CTransaction &tx, std::list<CTransaction>& removed)
457
489
{
458
490
// Remove transactions which depend on inputs of tx, recursively
@@ -513,17 +545,22 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
513
545
514
546
uint64_t checkTotal = 0 ;
515
547
548
+ CCoinsViewCache mempoolDuplicate (const_cast <CCoinsViewCache*>(pcoins));
549
+
516
550
LOCK (cs);
551
+ list<const CTxMemPoolEntry*> waitingOnDependants;
517
552
for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin (); it != mapTx.end (); it++) {
518
553
unsigned int i = 0 ;
519
554
checkTotal += it->second .GetTxSize ();
520
555
const CTransaction& tx = it->second .GetTx ();
556
+ bool fDependsWait = false ;
521
557
BOOST_FOREACH (const CTxIn &txin, tx.vin ) {
522
558
// Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
523
559
std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find (txin.prevout .hash );
524
560
if (it2 != mapTx.end ()) {
525
561
const CTransaction& tx2 = it2->second .GetTx ();
526
562
assert (tx2.vout .size () > txin.prevout .n && !tx2.vout [txin.prevout .n ].IsNull ());
563
+ fDependsWait = true ;
527
564
} else {
528
565
const CCoins* coins = pcoins->AccessCoins (txin.prevout .hash );
529
566
assert (coins && coins->IsAvailable (txin.prevout .n ));
@@ -535,6 +572,29 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
535
572
assert (it3->second .n == i);
536
573
i++;
537
574
}
575
+ if (fDependsWait )
576
+ waitingOnDependants.push_back (&it->second );
577
+ else {
578
+ CValidationState state; CTxUndo undo;
579
+ assert (CheckInputs (tx, state, mempoolDuplicate, false , 0 , false , NULL ));
580
+ UpdateCoins (tx, state, mempoolDuplicate, undo, 1000000 );
581
+ }
582
+ }
583
+ unsigned int stepsSinceLastRemove = 0 ;
584
+ while (!waitingOnDependants.empty ()) {
585
+ const CTxMemPoolEntry* entry = waitingOnDependants.front ();
586
+ waitingOnDependants.pop_front ();
587
+ CValidationState state;
588
+ if (!mempoolDuplicate.HaveInputs (entry->GetTx ())) {
589
+ waitingOnDependants.push_back (entry);
590
+ stepsSinceLastRemove++;
591
+ assert (stepsSinceLastRemove < waitingOnDependants.size ());
592
+ } else {
593
+ assert (CheckInputs (entry->GetTx (), state, mempoolDuplicate, false , 0 , false , NULL ));
594
+ CTxUndo undo;
595
+ UpdateCoins (entry->GetTx (), state, mempoolDuplicate, undo, 1000000 );
596
+ stepsSinceLastRemove = 0 ;
597
+ }
538
598
}
539
599
for (std::map<COutPoint, CInPoint>::const_iterator it = mapNextTx.begin (); it != mapNextTx.end (); it++) {
540
600
uint256 hash = it->second .ptx ->GetHash ();
0 commit comments