@@ -22,13 +22,22 @@ int64_t nTimeBestReceived = 0; // Used only to inform the wallet of when we las
2222
2323static const uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL ; // SHA256("main address relay")[0:8]
2424
25+ struct IteratorComparator
26+ {
27+ template <typename I>
28+ bool operator ()(const I& a, const I& b) const
29+ {
30+ return &(*a) < &(*b);
31+ }
32+ };
33+
2534struct COrphanTx {
2635 CTransactionRef tx;
2736 NodeId fromPeer;
2837};
2938
3039std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY (cs_main);
31- std::map<uint256 , std::set<uint256> > mapOrphanTransactionsByPrev GUARDED_BY (cs_main);
40+ std::map<COutPoint , std::set<std::map< uint256, COrphanTx>::iterator, IteratorComparator> > mapOrphanTransactionsByPrev GUARDED_BY (cs_main);
3241
3342void EraseOrphansFor (NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
3443
@@ -511,28 +520,30 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE
511520
512521 auto ret = mapOrphanTransactions.emplace (hash, COrphanTx{tx, peer});
513522 assert (ret.second );
514- for (const CTxIn& txin : tx->vin )
515- mapOrphanTransactionsByPrev[txin.prevout .hash ].insert (hash);
523+ for (const CTxIn& txin : tx->vin ) {
524+ mapOrphanTransactionsByPrev[txin.prevout ].insert (ret.first );
525+ }
516526
517- LogPrint (BCLog::MEMPOOL, " stored orphan tx %s (mapsz %u prevsz %u)\n " , hash.ToString (),
527+ LogPrint (BCLog::MEMPOOL, " stored orphan tx %s (mapsz %u outsz %u)\n " , hash.ToString (),
518528 mapOrphanTransactions.size (), mapOrphanTransactionsByPrev.size ());
519529 return true ;
520530}
521531
522- void static EraseOrphanTx (uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
532+ int static EraseOrphanTx (uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
523533{
524534 std::map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find (hash);
525535 if (it == mapOrphanTransactions.end ())
526- return ;
536+ return 0 ;
527537 for (const CTxIn& txin : it->second .tx ->vin ) {
528- std::map<uint256, std::set<uint256> >::iterator itPrev = mapOrphanTransactionsByPrev.find (txin.prevout . hash );
538+ auto itPrev = mapOrphanTransactionsByPrev.find (txin.prevout );
529539 if (itPrev == mapOrphanTransactionsByPrev.end ())
530540 continue ;
531- itPrev->second .erase (hash );
541+ itPrev->second .erase (it );
532542 if (itPrev->second .empty ())
533543 mapOrphanTransactionsByPrev.erase (itPrev);
534544 }
535545 mapOrphanTransactions.erase (it);
546+ return 1 ;
536547}
537548
538549void EraseOrphansFor (NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -542,8 +553,7 @@ void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
542553 while (iter != mapOrphanTransactions.end ()) {
543554 std::map<uint256, COrphanTx>::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid
544555 if (maybeErase->second .fromPeer == peer) {
545- EraseOrphanTx (maybeErase->second .tx ->GetHash ());
546- ++nErased;
556+ nErased += EraseOrphanTx (maybeErase->second .tx ->GetHash ());
547557 }
548558 }
549559 if (nErased > 0 ) LogPrint (BCLog::MEMPOOL, " Erased %d orphan tx from peer %d\n " , nErased, peer);
@@ -1413,7 +1423,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
14131423
14141424
14151425 else if (strCommand == NetMsgType::TX) {
1416- std::vector<uint256 > vWorkQueue;
1426+ std::deque<COutPoint > vWorkQueue;
14171427 std::vector<uint256> vEraseQueue;
14181428 CTransaction tx (deserialize, vRecv);
14191429 CTransactionRef ptx = MakeTransactionRef (tx);
@@ -1433,24 +1443,27 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
14331443 if (!tx.HasZerocoinSpendInputs () && AcceptToMemoryPool (mempool, state, ptx, true , &fMissingInputs , false , ignoreFees)) {
14341444 mempool.check (pcoinsTip);
14351445 RelayTransaction (tx, connman);
1436- vWorkQueue.push_back (inv.hash );
1446+ for (unsigned int i = 0 ; i < tx.vout .size (); i++) {
1447+ vWorkQueue.emplace_back (inv.hash , i);
1448+ }
14371449
14381450 LogPrint (BCLog::MEMPOOL, " %s : peer=%d %s : accepted %s (poolsz %u txn, %u kB)\n " ,
14391451 __func__, pfrom->id , pfrom->cleanSubVer , tx.GetHash ().ToString (),
14401452 mempool.size (), mempool.DynamicMemoryUsage () / 1000 );
14411453
14421454 // Recursively process any orphan transactions that depended on this one
14431455 std::set<NodeId> setMisbehaving;
1444- for (unsigned int i = 0 ; i < vWorkQueue.size (); i++) {
1445- std::map<uint256, std::set<uint256> >::iterator itByPrev = mapOrphanTransactionsByPrev.find (vWorkQueue[i]);
1456+ while (!vWorkQueue.empty ()) {
1457+ auto itByPrev = mapOrphanTransactionsByPrev.find (vWorkQueue.front ());
1458+ vWorkQueue.pop_front ();
14461459 if (itByPrev == mapOrphanTransactionsByPrev.end ())
14471460 continue ;
1448- for (std::set<uint256>::iterator mi = itByPrev->second .begin ();
1461+ for ( auto mi = itByPrev->second .begin ();
14491462 mi != itByPrev->second .end ();
14501463 ++mi) {
1451- const uint256 &orphanHash = *mi;
1452- const auto &orphanTx = mapOrphanTransactions[orphanHash]. tx ;
1453- NodeId fromPeer = mapOrphanTransactions[orphanHash] .fromPeer ;
1464+ const CTransactionRef& orphanTx = ( *mi)-> second . tx ;
1465+ const uint256& orphanHash = orphanTx-> GetHash () ;
1466+ NodeId fromPeer = (*mi)-> second .fromPeer ;
14541467 bool fMissingInputs2 = false ;
14551468 // Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
14561469 // resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get
@@ -1463,7 +1476,9 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
14631476 if (AcceptToMemoryPool (mempool, stateDummy, orphanTx, true , &fMissingInputs2 )) {
14641477 LogPrint (BCLog::MEMPOOL, " accepted orphan tx %s\n " , orphanHash.ToString ());
14651478 RelayTransaction (*orphanTx, connman);
1466- vWorkQueue.push_back (orphanHash);
1479+ for (unsigned int i = 0 ; i < orphanTx->vout .size (); i++) {
1480+ vWorkQueue.emplace_back (orphanHash, i);
1481+ }
14671482 vEraseQueue.push_back (orphanHash);
14681483 } else if (!fMissingInputs2 ) {
14691484 int nDos = 0 ;
0 commit comments