Skip to content

Commit d7461b8

Browse files
sipafurszy
authored andcommitted
Track orphan by prev COutPoint rather than prev hash
1 parent 93f43f0 commit d7461b8

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

src/net_processing.cpp

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,22 @@ int64_t nTimeBestReceived = 0; // Used only to inform the wallet of when we las
2222

2323
static 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+
2534
struct COrphanTx {
2635
CTransactionRef tx;
2736
NodeId fromPeer;
2837
};
2938

3039
std::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

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

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

Comments
 (0)