Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
Show First 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||
/// Age after which a stale block will no longer be served if requested as | /// Age after which a stale block will no longer be served if requested as | ||||
/// protection against fingerprinting. Set to one month, denominated in seconds. | /// protection against fingerprinting. Set to one month, denominated in seconds. | ||||
static const int STALE_RELAY_AGE_LIMIT = 30 * 24 * 60 * 60; | static const int STALE_RELAY_AGE_LIMIT = 30 * 24 * 60 * 60; | ||||
/// Age after which a block is considered historical for purposes of rate | /// Age after which a block is considered historical for purposes of rate | ||||
/// limiting block relay. Set to one week, denominated in seconds. | /// limiting block relay. Set to one week, denominated in seconds. | ||||
static const int HISTORICAL_BLOCK_AGE = 7 * 24 * 60 * 60; | static const int HISTORICAL_BLOCK_AGE = 7 * 24 * 60 * 60; | ||||
// How many non standard orphan do we consider from a node before ignoring it. | |||||
static const uint32_t MAX_NON_STANDARD_ORPHAN_PER_NODE = 5; | |||||
// Internal stuff | // Internal stuff | ||||
namespace { | namespace { | ||||
/** Number of nodes with fSyncStarted. */ | /** Number of nodes with fSyncStarted. */ | ||||
int nSyncStarted GUARDED_BY(cs_main) = 0; | int nSyncStarted GUARDED_BY(cs_main) = 0; | ||||
/** | /** | ||||
* Sources of received blocks, saved to be able to send them reject messages or | * Sources of received blocks, saved to be able to send them reject messages or | ||||
* ban them when processing happens afterwards. | * ban them when processing happens afterwards. | ||||
▲ Show 20 Lines • Show All 2,417 Lines • ▼ Show 20 Lines | else if (strCommand == NetMsgType::TX) { | ||||
LogPrint(BCLog::MEMPOOL, | LogPrint(BCLog::MEMPOOL, | ||||
"AcceptToMemoryPool: peer=%d: accepted %s " | "AcceptToMemoryPool: peer=%d: accepted %s " | ||||
"(poolsz %u txn, %u kB)\n", | "(poolsz %u txn, %u kB)\n", | ||||
pfrom->GetId(), tx.GetId().ToString(), g_mempool.size(), | pfrom->GetId(), tx.GetId().ToString(), g_mempool.size(), | ||||
g_mempool.DynamicMemoryUsage() / 1000); | g_mempool.DynamicMemoryUsage() / 1000); | ||||
// Recursively process any orphan transactions that depended on this | // Recursively process any orphan transactions that depended on this | ||||
// one | // one | ||||
std::set<NodeId> setMisbehaving; | std::unordered_map<NodeId, uint32_t> rejectCountPerNode; | ||||
while (!vWorkQueue.empty()) { | while (!vWorkQueue.empty()) { | ||||
auto itByPrev = | auto itByPrev = | ||||
mapOrphanTransactionsByPrev.find(vWorkQueue.front()); | mapOrphanTransactionsByPrev.find(vWorkQueue.front()); | ||||
vWorkQueue.pop_front(); | vWorkQueue.pop_front(); | ||||
if (itByPrev == mapOrphanTransactionsByPrev.end()) { | if (itByPrev == mapOrphanTransactionsByPrev.end()) { | ||||
continue; | continue; | ||||
} | } | ||||
for (auto mi = itByPrev->second.begin(); | for (auto mi = itByPrev->second.begin(); | ||||
mi != itByPrev->second.end(); ++mi) { | mi != itByPrev->second.end(); ++mi) { | ||||
const CTransactionRef &porphanTx = (*mi)->second.tx; | const CTransactionRef &porphanTx = (*mi)->second.tx; | ||||
const CTransaction &orphanTx = *porphanTx; | const CTransaction &orphanTx = *porphanTx; | ||||
const uint256 &orphanId = orphanTx.GetId(); | const uint256 &orphanId = orphanTx.GetId(); | ||||
NodeId fromPeer = (*mi)->second.fromPeer; | NodeId fromPeer = (*mi)->second.fromPeer; | ||||
bool fMissingInputs2 = false; | bool fMissingInputs2 = false; | ||||
// Use a dummy CValidationState so someone can't setup nodes | // Use a dummy CValidationState so someone can't setup nodes | ||||
// to counter-DoS based on orphan resolution (that is, | // to counter-DoS based on orphan resolution (that is, | ||||
// feeding people an invalid transaction based on LegitTxX | // feeding people an invalid transaction based on LegitTxX | ||||
// in order to get anyone relaying LegitTxX banned) | // in order to get anyone relaying LegitTxX banned) | ||||
CValidationState stateDummy; | CValidationState stateDummy; | ||||
if (setMisbehaving.count(fromPeer)) { | auto it = rejectCountPerNode.find(fromPeer); | ||||
if (it != rejectCountPerNode.end() && | |||||
it->second > MAX_NON_STANDARD_ORPHAN_PER_NODE) { | |||||
continue; | continue; | ||||
} | } | ||||
if (AcceptToMemoryPool(config, g_mempool, stateDummy, | if (AcceptToMemoryPool(config, g_mempool, stateDummy, | ||||
porphanTx, true, &fMissingInputs2)) { | porphanTx, true, &fMissingInputs2)) { | ||||
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", | LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", | ||||
orphanId.ToString()); | orphanId.ToString()); | ||||
RelayTransaction(orphanTx, connman); | RelayTransaction(orphanTx, connman); | ||||
for (size_t i = 0; i < orphanTx.vout.size(); i++) { | for (size_t i = 0; i < orphanTx.vout.size(); i++) { | ||||
vWorkQueue.emplace_back(orphanId, i); | vWorkQueue.emplace_back(orphanId, i); | ||||
} | } | ||||
vEraseQueue.push_back(orphanId); | vEraseQueue.push_back(orphanId); | ||||
} else if (!fMissingInputs2) { | } else if (!fMissingInputs2) { | ||||
int nDos = 0; | int nDos = 0; | ||||
if (stateDummy.IsInvalid(nDos) && nDos > 0) { | if (stateDummy.IsInvalid(nDos)) { | ||||
rejectCountPerNode[fromPeer]++; | |||||
if (nDos > 0) { | |||||
// Punish peer that gave us an invalid orphan tx | // Punish peer that gave us an invalid orphan tx | ||||
Misbehaving(fromPeer, nDos, "invalid-orphan-tx"); | Misbehaving(fromPeer, nDos, | ||||
setMisbehaving.insert(fromPeer); | "invalid-orphan-tx"); | ||||
LogPrint(BCLog::MEMPOOL, | LogPrint(BCLog::MEMPOOL, | ||||
" invalid orphan tx %s\n", | " invalid orphan tx %s\n", | ||||
orphanId.ToString()); | orphanId.ToString()); | ||||
} | } | ||||
} | |||||
// Has inputs but not accepted to mempool | // Has inputs but not accepted to mempool | ||||
// Probably non-standard or insufficient fee/priority | // Probably non-standard or insufficient fee/priority | ||||
LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", | LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", | ||||
orphanId.ToString()); | orphanId.ToString()); | ||||
vEraseQueue.push_back(orphanId); | vEraseQueue.push_back(orphanId); | ||||
if (!stateDummy.CorruptionPossible()) { | if (!stateDummy.CorruptionPossible()) { | ||||
// Do not use rejection cache for witness | // Do not use rejection cache for witness | ||||
// transactions or witness-stripped transactions, as | // transactions or witness-stripped transactions, as | ||||
▲ Show 20 Lines • Show All 1,791 Lines • Show Last 20 Lines |