Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
Show First 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | |||||
/// How many non standard orphan do we consider from a node before ignoring it. | /// How many non standard orphan do we consider from a node before ignoring it. | ||||
static constexpr uint32_t MAX_NON_STANDARD_ORPHAN_PER_NODE = 5; | static constexpr uint32_t MAX_NON_STANDARD_ORPHAN_PER_NODE = 5; | ||||
struct COrphanTx { | struct COrphanTx { | ||||
// When modifying, adapt the copy of this definition in tests/DoS_tests. | // When modifying, adapt the copy of this definition in tests/DoS_tests. | ||||
CTransactionRef tx; | CTransactionRef tx; | ||||
NodeId fromPeer; | NodeId fromPeer; | ||||
int64_t nTimeExpire; | int64_t nTimeExpire; | ||||
size_t list_pos; | |||||
}; | }; | ||||
RecursiveMutex g_cs_orphans; | RecursiveMutex g_cs_orphans; | ||||
std::map<TxId, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans); | std::map<TxId, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans); | ||||
void EraseOrphansFor(NodeId peer); | void EraseOrphansFor(NodeId peer); | ||||
/** | /** | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | struct IteratorComparator { | ||||
template <typename I> bool operator()(const I &a, const I &b) const { | template <typename I> bool operator()(const I &a, const I &b) const { | ||||
return &(*a) < &(*b); | return &(*a) < &(*b); | ||||
} | } | ||||
}; | }; | ||||
std::map<COutPoint, | std::map<COutPoint, | ||||
std::set<std::map<TxId, COrphanTx>::iterator, IteratorComparator>> | std::set<std::map<TxId, COrphanTx>::iterator, IteratorComparator>> | ||||
mapOrphanTransactionsByPrev GUARDED_BY(g_cs_orphans); | mapOrphanTransactionsByPrev GUARDED_BY(g_cs_orphans); | ||||
//! For random eviction | |||||
std::vector<std::map<TxId, COrphanTx>::iterator> | |||||
g_orphan_list GUARDED_BY(g_cs_orphans); | |||||
static size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0; | static size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0; | ||||
static std::vector<std::pair<TxHash, CTransactionRef>> | static std::vector<std::pair<TxHash, CTransactionRef>> | ||||
vExtraTxnForCompact GUARDED_BY(g_cs_orphans); | vExtraTxnForCompact GUARDED_BY(g_cs_orphans); | ||||
} // namespace | } // namespace | ||||
namespace { | namespace { | ||||
struct CBlockReject { | struct CBlockReject { | ||||
uint8_t chRejectCode; | uint8_t chRejectCode; | ||||
▲ Show 20 Lines • Show All 782 Lines • ▼ Show 20 Lines | bool AddOrphanTx(const CTransactionRef &tx, NodeId peer) | ||||
if (sz > MAX_STANDARD_TX_SIZE) { | if (sz > MAX_STANDARD_TX_SIZE) { | ||||
LogPrint(BCLog::MEMPOOL, | LogPrint(BCLog::MEMPOOL, | ||||
"ignoring large orphan tx (size: %u, hash: %s)\n", sz, | "ignoring large orphan tx (size: %u, hash: %s)\n", sz, | ||||
txid.ToString()); | txid.ToString()); | ||||
return false; | return false; | ||||
} | } | ||||
auto ret = mapOrphanTransactions.emplace( | auto ret = mapOrphanTransactions.emplace( | ||||
txid, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME}); | txid, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME, | ||||
g_orphan_list.size()}); | |||||
assert(ret.second); | assert(ret.second); | ||||
g_orphan_list.push_back(ret.first); | |||||
for (const CTxIn &txin : tx->vin) { | for (const CTxIn &txin : tx->vin) { | ||||
mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first); | mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first); | ||||
} | } | ||||
AddToCompactExtraTransactions(tx); | AddToCompactExtraTransactions(tx); | ||||
LogPrint(BCLog::MEMPOOL, "stored orphan tx %s (mapsz %u outsz %u)\n", | LogPrint(BCLog::MEMPOOL, "stored orphan tx %s (mapsz %u outsz %u)\n", | ||||
txid.ToString(), mapOrphanTransactions.size(), | txid.ToString(), mapOrphanTransactions.size(), | ||||
Show All 11 Lines | for (const CTxIn &txin : it->second.tx->vin) { | ||||
if (itPrev == mapOrphanTransactionsByPrev.end()) { | if (itPrev == mapOrphanTransactionsByPrev.end()) { | ||||
continue; | continue; | ||||
} | } | ||||
itPrev->second.erase(it); | itPrev->second.erase(it); | ||||
if (itPrev->second.empty()) { | if (itPrev->second.empty()) { | ||||
mapOrphanTransactionsByPrev.erase(itPrev); | mapOrphanTransactionsByPrev.erase(itPrev); | ||||
} | } | ||||
} | } | ||||
size_t old_pos = it->second.list_pos; | |||||
assert(g_orphan_list[old_pos] == it); | |||||
if (old_pos + 1 != g_orphan_list.size()) { | |||||
// Unless we're deleting the last entry in g_orphan_list, move the last | |||||
// entry to the position we're deleting. | |||||
auto it_last = g_orphan_list.back(); | |||||
g_orphan_list[old_pos] = it_last; | |||||
it_last->second.list_pos = old_pos; | |||||
} | |||||
g_orphan_list.pop_back(); | |||||
mapOrphanTransactions.erase(it); | mapOrphanTransactions.erase(it); | ||||
return 1; | return 1; | ||||
} | } | ||||
void EraseOrphansFor(NodeId peer) { | void EraseOrphansFor(NodeId peer) { | ||||
LOCK(g_cs_orphans); | LOCK(g_cs_orphans); | ||||
int nErased = 0; | int nErased = 0; | ||||
auto iter = mapOrphanTransactions.begin(); | auto iter = mapOrphanTransactions.begin(); | ||||
Show All 37 Lines | if (nNextSweep <= nNow) { | ||||
if (nErased > 0) { | if (nErased > 0) { | ||||
LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx due to expiration\n", | LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx due to expiration\n", | ||||
nErased); | nErased); | ||||
} | } | ||||
} | } | ||||
FastRandomContext rng; | FastRandomContext rng; | ||||
while (mapOrphanTransactions.size() > nMaxOrphans) { | while (mapOrphanTransactions.size() > nMaxOrphans) { | ||||
// Evict a random orphan: | // Evict a random orphan: | ||||
const TxId randomTxId(rng.rand256()); | size_t randompos = rng.randrange(g_orphan_list.size()); | ||||
auto it = mapOrphanTransactions.lower_bound(randomTxId); | EraseOrphanTx(g_orphan_list[randompos]->first); | ||||
if (it == mapOrphanTransactions.end()) { | |||||
it = mapOrphanTransactions.begin(); | |||||
} | |||||
EraseOrphanTx(it->first); | |||||
++nEvicted; | ++nEvicted; | ||||
} | } | ||||
return nEvicted; | return nEvicted; | ||||
} | } | ||||
/** | /** | ||||
* Mark a misbehaving peer to be banned depending upon the value of `-banscore`. | * Mark a misbehaving peer to be banned depending upon the value of `-banscore`. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 3,851 Lines • Show Last 20 Lines |