Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
Show First 20 Lines • Show All 273 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static constexpr uint32_t MAX_GETCFHEADERS_SIZE = 2000; | static constexpr uint32_t MAX_GETCFHEADERS_SIZE = 2000; | ||||
/** | /** | ||||
* the maximum percentage of addresses from our addrman to return in response | * the maximum percentage of addresses from our addrman to return in response | ||||
* to a getaddr message. | * to a getaddr message. | ||||
*/ | */ | ||||
static constexpr size_t MAX_PCT_ADDR_TO_SEND = 23; | static constexpr size_t MAX_PCT_ADDR_TO_SEND = 23; | ||||
/// 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; | |||||
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; | size_t list_pos; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 2,242 Lines • ▼ Show 20 Lines | |||||
* this function. This set may be added to if accepting an orphan causes its | * this function. This set may be added to if accepting an orphan causes its | ||||
* children to be reconsidered. | * children to be reconsidered. | ||||
*/ | */ | ||||
void PeerManager::ProcessOrphanTx(const Config &config, | void PeerManager::ProcessOrphanTx(const Config &config, | ||||
std::set<TxId> &orphan_work_set) | std::set<TxId> &orphan_work_set) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
AssertLockHeld(g_cs_orphans); | AssertLockHeld(g_cs_orphans); | ||||
std::unordered_map<NodeId, uint32_t> rejectCountPerNode; | |||||
while (!orphan_work_set.empty()) { | while (!orphan_work_set.empty()) { | ||||
const TxId orphanTxId = *orphan_work_set.begin(); | const TxId orphanTxId = *orphan_work_set.begin(); | ||||
orphan_work_set.erase(orphan_work_set.begin()); | orphan_work_set.erase(orphan_work_set.begin()); | ||||
auto orphan_it = mapOrphanTransactions.find(orphanTxId); | auto orphan_it = mapOrphanTransactions.find(orphanTxId); | ||||
if (orphan_it == mapOrphanTransactions.end()) { | if (orphan_it == mapOrphanTransactions.end()) { | ||||
continue; | continue; | ||||
} | } | ||||
const CTransactionRef porphanTx = orphan_it->second.tx; | const CTransactionRef porphanTx = orphan_it->second.tx; | ||||
const CTransaction &orphanTx = *porphanTx; | const CTransaction &orphanTx = *porphanTx; | ||||
NodeId fromPeer = orphan_it->second.fromPeer; | NodeId fromPeer = orphan_it->second.fromPeer; | ||||
// Use a new TxValidationState because orphans come from different peers | // Use a new TxValidationState because orphans come from different peers | ||||
// (and we call MaybePunishNodeForTx based on the source peer from the | // (and we call MaybePunishNodeForTx based on the source peer from the | ||||
// orphan map, not based on the peer that relayed the previous | // orphan map, not based on the peer that relayed the previous | ||||
// transaction). | // transaction). | ||||
TxValidationState orphan_state; | TxValidationState orphan_state; | ||||
auto it = rejectCountPerNode.find(fromPeer); | |||||
if (it != rejectCountPerNode.end() && | |||||
it->second > MAX_NON_STANDARD_ORPHAN_PER_NODE) { | |||||
continue; | |||||
} | |||||
if (AcceptToMemoryPool(config, m_mempool, orphan_state, porphanTx, | if (AcceptToMemoryPool(config, m_mempool, orphan_state, porphanTx, | ||||
false /* bypass_limits */, | false /* bypass_limits */, | ||||
Amount::zero() /* nAbsurdFee */)) { | Amount::zero() /* nAbsurdFee */)) { | ||||
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", | LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", | ||||
orphanTxId.ToString()); | orphanTxId.ToString()); | ||||
RelayTransaction(orphanTxId, m_connman); | RelayTransaction(orphanTxId, m_connman); | ||||
for (size_t i = 0; i < orphanTx.vout.size(); i++) { | for (size_t i = 0; i < orphanTx.vout.size(); i++) { | ||||
auto it_by_prev = | auto it_by_prev = | ||||
mapOrphanTransactionsByPrev.find(COutPoint(orphanTxId, i)); | mapOrphanTransactionsByPrev.find(COutPoint(orphanTxId, i)); | ||||
if (it_by_prev != mapOrphanTransactionsByPrev.end()) { | if (it_by_prev != mapOrphanTransactionsByPrev.end()) { | ||||
for (const auto &elem : it_by_prev->second) { | for (const auto &elem : it_by_prev->second) { | ||||
orphan_work_set.insert(elem->first); | orphan_work_set.insert(elem->first); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
EraseOrphanTx(orphanTxId); | EraseOrphanTx(orphanTxId); | ||||
break; | break; | ||||
} else if (orphan_state.GetResult() != | } else if (orphan_state.GetResult() != | ||||
TxValidationResult::TX_MISSING_INPUTS) { | TxValidationResult::TX_MISSING_INPUTS) { | ||||
if (orphan_state.IsInvalid()) { | if (orphan_state.IsInvalid()) { | ||||
// Punish peer that gave us an invalid orphan tx | |||||
MaybePunishNodeForTx(fromPeer, orphan_state); | |||||
LogPrint(BCLog::MEMPOOL, | LogPrint(BCLog::MEMPOOL, | ||||
" invalid orphan tx %s from peer=%d. %s\n", | " invalid orphan tx %s from peer=%d. %s\n", | ||||
orphanTxId.ToString(), fromPeer, | orphanTxId.ToString(), fromPeer, | ||||
orphan_state.ToString()); | orphan_state.ToString()); | ||||
// Punish peer that gave us an invalid orphan tx | |||||
MaybePunishNodeForTx(fromPeer, orphan_state); | |||||
} | } | ||||
// Has inputs but not accepted to mempool | // Has inputs but not accepted to mempool | ||||
// Probably non-standard or insufficient fee | // Probably non-standard or insufficient fee | ||||
LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", | LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", | ||||
orphanTxId.ToString()); | orphanTxId.ToString()); | ||||
assert(recentRejects); | assert(recentRejects); | ||||
recentRejects->insert(orphanTxId); | recentRejects->insert(orphanTxId); | ||||
▲ Show 20 Lines • Show All 3,374 Lines • Show Last 20 Lines |