@@ -88,12 +88,21 @@ CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
88
88
CTxMemPool mempool (::minRelayTxFee);
89
89
FeeFilterRounder filterRounder (::minRelayTxFee);
90
90
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
+
91
100
struct COrphanTx {
92
101
CTransaction tx;
93
102
NodeId fromPeer;
94
103
};
95
104
map<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);
97
106
void EraseOrphansFor (NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
98
107
99
108
/* *
@@ -632,31 +641,33 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c
632
641
return false ;
633
642
}
634
643
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
+ }
639
649
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 (),
641
651
mapOrphanTransactions.size (), mapOrphanTransactionsByPrev.size ());
642
652
return true ;
643
653
}
644
654
645
- void static EraseOrphanTx (uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
655
+ int static EraseOrphanTx (uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
646
656
{
647
657
map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find (hash);
648
658
if (it == mapOrphanTransactions.end ())
649
- return ;
659
+ return 0 ;
650
660
BOOST_FOREACH (const CTxIn& txin, it->second .tx .vin )
651
661
{
652
- map<uint256, set<uint256> >::iterator itPrev = mapOrphanTransactionsByPrev.find (txin.prevout . hash );
662
+ auto itPrev = mapOrphanTransactionsByPrev.find (txin.prevout );
653
663
if (itPrev == mapOrphanTransactionsByPrev.end ())
654
664
continue ;
655
- itPrev->second .erase (hash );
665
+ itPrev->second .erase (it );
656
666
if (itPrev->second .empty ())
657
667
mapOrphanTransactionsByPrev.erase (itPrev);
658
668
}
659
669
mapOrphanTransactions.erase (it);
670
+ return 1 ;
660
671
}
661
672
662
673
void EraseOrphansFor (NodeId peer)
@@ -668,8 +679,7 @@ void EraseOrphansFor(NodeId peer)
668
679
map<uint256, COrphanTx>::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid
669
680
if (maybeErase->second .fromPeer == peer)
670
681
{
671
- EraseOrphanTx (maybeErase->second .tx .GetHash ());
672
- ++nErased;
682
+ nErased += EraseOrphanTx (maybeErase->second .tx .GetHash ());
673
683
}
674
684
}
675
685
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,
5019
5029
return true ;
5020
5030
}
5021
5031
5022
- vector<uint256 > vWorkQueue;
5032
+ deque<COutPoint > vWorkQueue;
5023
5033
vector<uint256> vEraseQueue;
5024
5034
CTransaction tx;
5025
5035
vRecv >> tx;
@@ -5038,7 +5048,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
5038
5048
if (!AlreadyHave (inv) && AcceptToMemoryPool (mempool, state, tx, true , &fMissingInputs )) {
5039
5049
mempool.check (pcoinsTip);
5040
5050
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
+ }
5042
5054
5043
5055
LogPrint (" mempool" , " AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n " ,
5044
5056
pfrom->id ,
@@ -5047,18 +5059,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
5047
5059
5048
5060
// Recursively process any orphan transactions that depended on this one
5049
5061
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 ( );
5053
5065
if (itByPrev == mapOrphanTransactionsByPrev.end ())
5054
5066
continue ;
5055
- for (set<uint256>::iterator mi = itByPrev->second .begin ();
5067
+ for (auto mi = itByPrev->second .begin ();
5056
5068
mi != itByPrev->second .end ();
5057
5069
++mi)
5058
5070
{
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 ;
5062
5074
bool fMissingInputs2 = false ;
5063
5075
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
5064
5076
// 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,
5071
5083
if (AcceptToMemoryPool (mempool, stateDummy, orphanTx, true , &fMissingInputs2 )) {
5072
5084
LogPrint (" mempool" , " accepted orphan tx %s\n " , orphanHash.ToString ());
5073
5085
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
+ }
5075
5089
vEraseQueue.push_back (orphanHash);
5076
5090
}
5077
5091
else if (!fMissingInputs2 )
0 commit comments