Skip to content

Commit 1b0bcc5

Browse files
sipagmaxwell
authored andcommitted
Track orphan by prev COutPoint rather than prev hash
1 parent 3e4cf8f commit 1b0bcc5

File tree

1 file changed

+36
-22
lines changed

1 file changed

+36
-22
lines changed

src/main.cpp

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,21 @@ CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
8888
CTxMemPool mempool(::minRelayTxFee);
8989
FeeFilterRounder 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+
91100
struct COrphanTx {
92101
CTransaction tx;
93102
NodeId fromPeer;
94103
};
95104
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);
97106
void 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

662673
void 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

Comments
 (0)