@@ -88,12 +88,21 @@ CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
8888CTxMemPool mempool (::minRelayTxFee);
8989FeeFilterRounder filterRounder (::minRelayTxFee);
9090
91+ struct IteratorComparator
92+ {
93+ template <typename I>
94+ bool operator ()(const I& a, const I& b)
95+ {
96+ return &(*a) < &(*b);
97+ }
98+ };
99+
91100struct COrphanTx {
92101 CTransaction tx;
93102 NodeId fromPeer;
94103};
95104map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY (cs_main);
96- map<uint256 , set<uint256> > mapOrphanTransactionsByPrev GUARDED_BY (cs_main);
105+ map<COutPoint , set<map< uint256, COrphanTx>::iterator, IteratorComparator> > mapOrphanTransactionsByPrev GUARDED_BY (cs_main);
97106void EraseOrphansFor (NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
98107
99108/* *
@@ -632,31 +641,33 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c
632641 return false ;
633642 }
634643
635- mapOrphanTransactions[hash].tx = tx;
636- mapOrphanTransactions[hash].fromPeer = peer;
637- BOOST_FOREACH (const CTxIn& txin, tx.vin )
638- mapOrphanTransactionsByPrev[txin.prevout .hash ].insert (hash);
644+ auto ret = mapOrphanTransactions.emplace (hash, COrphanTx{tx, peer});
645+ assert (ret.second );
646+ BOOST_FOREACH (const CTxIn& txin, tx.vin ) {
647+ mapOrphanTransactionsByPrev[txin.prevout ].insert (ret.first );
648+ }
639649
640- LogPrint (" mempool" , " stored orphan tx %s (mapsz %u prevsz %u)\n " , hash.ToString (),
650+ LogPrint (" mempool" , " stored orphan tx %s (mapsz %u outsz %u)\n " , hash.ToString (),
641651 mapOrphanTransactions.size (), mapOrphanTransactionsByPrev.size ());
642652 return true ;
643653}
644654
645- void static EraseOrphanTx (uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
655+ int static EraseOrphanTx (uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
646656{
647657 map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find (hash);
648658 if (it == mapOrphanTransactions.end ())
649- return ;
659+ return 0 ;
650660 BOOST_FOREACH (const CTxIn& txin, it->second .tx .vin )
651661 {
652- map<uint256, set<uint256> >::iterator itPrev = mapOrphanTransactionsByPrev.find (txin.prevout . hash );
662+ auto itPrev = mapOrphanTransactionsByPrev.find (txin.prevout );
653663 if (itPrev == mapOrphanTransactionsByPrev.end ())
654664 continue ;
655- itPrev->second .erase (hash );
665+ itPrev->second .erase (it );
656666 if (itPrev->second .empty ())
657667 mapOrphanTransactionsByPrev.erase (itPrev);
658668 }
659669 mapOrphanTransactions.erase (it);
670+ return 1 ;
660671}
661672
662673void EraseOrphansFor (NodeId peer)
@@ -668,8 +679,7 @@ void EraseOrphansFor(NodeId peer)
668679 map<uint256, COrphanTx>::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid
669680 if (maybeErase->second .fromPeer == peer)
670681 {
671- EraseOrphanTx (maybeErase->second .tx .GetHash ());
672- ++nErased;
682+ nErased += EraseOrphanTx (maybeErase->second .tx .GetHash ());
673683 }
674684 }
675685 if (nErased > 0 ) LogPrint (" mempool" , " Erased %d orphan tx from peer %d\n " , nErased, peer);
@@ -5019,7 +5029,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
50195029 return true ;
50205030 }
50215031
5022- vector<uint256 > vWorkQueue;
5032+ deque<COutPoint > vWorkQueue;
50235033 vector<uint256> vEraseQueue;
50245034 CTransaction tx;
50255035 vRecv >> tx;
@@ -5038,7 +5048,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
50385048 if (!AlreadyHave (inv) && AcceptToMemoryPool (mempool, state, tx, true , &fMissingInputs )) {
50395049 mempool.check (pcoinsTip);
50405050 RelayTransaction (tx);
5041- vWorkQueue.push_back (inv.hash );
5051+ for (unsigned int i = 0 ; i < tx.vout .size (); i++) {
5052+ vWorkQueue.emplace_back (inv.hash , i);
5053+ }
50425054
50435055 LogPrint (" mempool" , " AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n " ,
50445056 pfrom->id ,
@@ -5047,18 +5059,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
50475059
50485060 // Recursively process any orphan transactions that depended on this one
50495061 set<NodeId> setMisbehaving;
5050- for ( unsigned int i = 0 ; i < vWorkQueue.size (); i++)
5051- {
5052- map<uint256, set<uint256> >::iterator itByPrev = mapOrphanTransactionsByPrev. find (vWorkQueue[i] );
5062+ while (! vWorkQueue.empty ()) {
5063+ auto itByPrev = mapOrphanTransactionsByPrev. find (vWorkQueue. front ());
5064+ vWorkQueue. pop_front ( );
50535065 if (itByPrev == mapOrphanTransactionsByPrev.end ())
50545066 continue ;
5055- for (set<uint256>::iterator mi = itByPrev->second .begin ();
5067+ for (auto mi = itByPrev->second .begin ();
50565068 mi != itByPrev->second .end ();
50575069 ++mi)
50585070 {
5059- const uint256& orphanHash = *mi;
5060- const CTransaction& orphanTx = mapOrphanTransactions[orphanHash]. tx ;
5061- NodeId fromPeer = mapOrphanTransactions[orphanHash] .fromPeer ;
5071+ const CTransaction& orphanTx = ( *mi)-> second . tx ;
5072+ const uint256& orphanHash = orphanTx. GetHash () ;
5073+ NodeId fromPeer = (*mi)-> second .fromPeer ;
50625074 bool fMissingInputs2 = false ;
50635075 // Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
50645076 // resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get
@@ -5071,7 +5083,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
50715083 if (AcceptToMemoryPool (mempool, stateDummy, orphanTx, true , &fMissingInputs2 )) {
50725084 LogPrint (" mempool" , " accepted orphan tx %s\n " , orphanHash.ToString ());
50735085 RelayTransaction (orphanTx);
5074- vWorkQueue.push_back (orphanHash);
5086+ for (unsigned int i = 0 ; i < orphanTx.vout .size (); i++) {
5087+ vWorkQueue.emplace_back (orphanHash, i);
5088+ }
50755089 vEraseQueue.push_back (orphanHash);
50765090 }
50775091 else if (!fMissingInputs2 )
0 commit comments