Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
Show First 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static constexpr std::chrono::hours AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24}; | static constexpr std::chrono::hours AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24}; | ||||
/** | /** | ||||
* Average delay between peer address broadcasts. | * Average delay between peer address broadcasts. | ||||
*/ | */ | ||||
static const std::chrono::seconds AVG_ADDRESS_BROADCAST_INTERVAL{30}; | static const std::chrono::seconds AVG_ADDRESS_BROADCAST_INTERVAL{30}; | ||||
/** | /** | ||||
* Average delay between trickled inventory transmissions in seconds. | * Average delay between trickled inventory transmissions in seconds. | ||||
* Blocks and whitelisted receivers bypass this, outbound peers get half this | * Blocks and peers with noban permission bypass this, outbound peers | ||||
* delay. | * get half this delay. | ||||
*/ | */ | ||||
static const unsigned int INVENTORY_BROADCAST_INTERVAL = 5; | static const unsigned int INVENTORY_BROADCAST_INTERVAL = 5; | ||||
/** | /** | ||||
* Maximum rate of inventory items to send per second. | * Maximum rate of inventory items to send per second. | ||||
* Limits the impact of low-fee transaction floods. | * Limits the impact of low-fee transaction floods. | ||||
*/ | */ | ||||
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND = 7; | static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND = 7; | ||||
/** Maximum number of inventory items to send per transmission. */ | /** Maximum number of inventory items to send per transmission. */ | ||||
▲ Show 20 Lines • Show All 2,192 Lines • ▼ Show 20 Lines | if (!m_chainman.ProcessNewBlockHeaders(config, headers, state, | ||||
if (::ChainstateActive().IsInitialBlockDownload() && | if (::ChainstateActive().IsInitialBlockDownload() && | ||||
nCount != MAX_HEADERS_RESULTS) { | nCount != MAX_HEADERS_RESULTS) { | ||||
// When nCount < MAX_HEADERS_RESULTS, we know we have no more | // When nCount < MAX_HEADERS_RESULTS, we know we have no more | ||||
// headers to fetch from this peer. | // headers to fetch from this peer. | ||||
if (nodestate->pindexBestKnownBlock && | if (nodestate->pindexBestKnownBlock && | ||||
nodestate->pindexBestKnownBlock->nChainWork < | nodestate->pindexBestKnownBlock->nChainWork < | ||||
nMinimumChainWork) { | nMinimumChainWork) { | ||||
// This peer has too little work on their headers chain to help | // This peer has too little work on their headers chain to help | ||||
// us sync -- disconnect if using an outbound slot (unless | // us sync -- disconnect if it is an outbound disconnection | ||||
// whitelisted or addnode). | // candidate. | ||||
// Note: We compare their tip to nMinimumChainWork (rather than | // Note: We compare their tip to nMinimumChainWork (rather than | ||||
// ::ChainActive().Tip()) because we won't start block download | // ::ChainActive().Tip()) because we won't start block download | ||||
// until we have a headers chain that has at least | // until we have a headers chain that has at least | ||||
// nMinimumChainWork, even if a peer has a chain past our tip, | // nMinimumChainWork, even if a peer has a chain past our tip, | ||||
// as an anti-DoS measure. | // as an anti-DoS measure. | ||||
if (pfrom.IsOutboundOrBlockRelayConn()) { | if (pfrom.IsOutboundOrBlockRelayConn()) { | ||||
LogPrintf("Disconnecting outbound peer %d -- headers " | LogPrintf("Disconnecting outbound peer %d -- headers " | ||||
"chain has insufficient work\n", | "chain has insufficient work\n", | ||||
▲ Show 20 Lines • Show All 758 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::INV) { | ||||
strprintf("inv message size = %u", vInv.size())); | strprintf("inv message size = %u", vInv.size())); | ||||
return; | return; | ||||
} | } | ||||
// We won't accept tx inv's if we're in blocks-only mode, or this is a | // We won't accept tx inv's if we're in blocks-only mode, or this is a | ||||
// block-relay-only peer | // block-relay-only peer | ||||
bool fBlocksOnly = !g_relay_txes || (pfrom.m_tx_relay == nullptr); | bool fBlocksOnly = !g_relay_txes || (pfrom.m_tx_relay == nullptr); | ||||
// Allow whitelisted peers to send data other than blocks in blocks only | // Allow peers with relay permission to send data other than blocks | ||||
// mode if whitelistrelay is true | // in blocks only mode | ||||
if (pfrom.HasPermission(PF_RELAY)) { | if (pfrom.HasPermission(PF_RELAY)) { | ||||
fBlocksOnly = false; | fBlocksOnly = false; | ||||
} | } | ||||
const auto current_time = GetTime<std::chrono::microseconds>(); | const auto current_time = GetTime<std::chrono::microseconds>(); | ||||
std::optional<BlockHash> best_block; | std::optional<BlockHash> best_block; | ||||
auto logInv = [&](const CInv &inv, bool fAlreadyHave) { | auto logInv = [&](const CInv &inv, bool fAlreadyHave) { | ||||
▲ Show 20 Lines • Show All 433 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::TX) { | ||||
recentRejects->insert(tx.GetId()); | recentRejects->insert(tx.GetId()); | ||||
m_txrequest.ForgetInvId(tx.GetId()); | m_txrequest.ForgetInvId(tx.GetId()); | ||||
if (RecursiveDynamicUsage(*ptx) < 100000) { | if (RecursiveDynamicUsage(*ptx) < 100000) { | ||||
AddToCompactExtraTransactions(ptx); | AddToCompactExtraTransactions(ptx); | ||||
} | } | ||||
if (pfrom.HasPermission(PF_FORCERELAY)) { | if (pfrom.HasPermission(PF_FORCERELAY)) { | ||||
// Always relay transactions received from whitelisted peers, | // Always relay transactions received from peers with | ||||
// even if they were already in the mempool, allowing the node | // forcerelay permission, even if they were already in the | ||||
// to function as a gateway for | // mempool, allowing the node to function as a gateway for | ||||
// nodes hidden behind it. | // nodes hidden behind it. | ||||
if (!m_mempool.exists(tx.GetId())) { | if (!m_mempool.exists(tx.GetId())) { | ||||
LogPrintf("Not relaying non-mempool transaction %s from " | LogPrintf("Not relaying non-mempool transaction %s from " | ||||
"whitelisted peer=%d\n", | "forcerelay peer=%d\n", | ||||
tx.GetId().ToString(), pfrom.GetId()); | tx.GetId().ToString(), pfrom.GetId()); | ||||
} else { | } else { | ||||
LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", | LogPrintf("Force relaying tx %s from peer=%d\n", | ||||
tx.GetId().ToString(), pfrom.GetId()); | tx.GetId().ToString(), pfrom.GetId()); | ||||
RelayTransaction(tx.GetId(), m_connman); | RelayTransaction(tx.GetId(), m_connman); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// If a tx has been detected by recentRejects, we will have reached | // If a tx has been detected by recentRejects, we will have reached | ||||
// this point and the tx will have been ignored. Because we haven't run | // this point and the tx will have been ignored. Because we haven't run | ||||
▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::CMPCTBLOCK) { | ||||
} | } | ||||
} | } | ||||
PartiallyDownloadedBlock &partialBlock = | PartiallyDownloadedBlock &partialBlock = | ||||
*(*queuedBlockIt)->partialBlock; | *(*queuedBlockIt)->partialBlock; | ||||
ReadStatus status = | ReadStatus status = | ||||
partialBlock.InitData(cmpctblock, vExtraTxnForCompact); | partialBlock.InitData(cmpctblock, vExtraTxnForCompact); | ||||
if (status == READ_STATUS_INVALID) { | if (status == READ_STATUS_INVALID) { | ||||
// Reset in-flight state in case of whitelist | // Reset in-flight state in case Misbehaving does not | ||||
// result in a disconnect | |||||
MarkBlockAsReceived(pindex->GetBlockHash()); | MarkBlockAsReceived(pindex->GetBlockHash()); | ||||
Misbehaving(pfrom, 100, "invalid compact block"); | Misbehaving(pfrom, 100, "invalid compact block"); | ||||
return; | return; | ||||
} else if (status == READ_STATUS_FAILED) { | } else if (status == READ_STATUS_FAILED) { | ||||
// Duplicate txindices, the block is now in-flight, so | // Duplicate txindices, the block is now in-flight, so | ||||
// just request it. | // just request it. | ||||
std::vector<CInv> vInv(1); | std::vector<CInv> vInv(1); | ||||
vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); | vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); | ||||
▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::BLOCKTXN) { | ||||
pfrom.GetId()); | pfrom.GetId()); | ||||
return; | return; | ||||
} | } | ||||
PartiallyDownloadedBlock &partialBlock = | PartiallyDownloadedBlock &partialBlock = | ||||
*it->second.second->partialBlock; | *it->second.second->partialBlock; | ||||
ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn); | ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn); | ||||
if (status == READ_STATUS_INVALID) { | if (status == READ_STATUS_INVALID) { | ||||
// Reset in-flight state in case of whitelist. | // Reset in-flight state in case of Misbehaving does not | ||||
// result in a disconnect. | |||||
MarkBlockAsReceived(resp.blockhash); | MarkBlockAsReceived(resp.blockhash); | ||||
Misbehaving( | Misbehaving( | ||||
pfrom, 100, | pfrom, 100, | ||||
"invalid compact block/non-matching block transactions"); | "invalid compact block/non-matching block transactions"); | ||||
return; | return; | ||||
} else if (status == READ_STATUS_FAILED) { | } else if (status == READ_STATUS_FAILED) { | ||||
// Might have collided, fall back to getdata now :( | // Might have collided, fall back to getdata now :( | ||||
std::vector<CInv> invs; | std::vector<CInv> invs; | ||||
▲ Show 20 Lines • Show All 1,642 Lines • ▼ Show 20 Lines | if (!vInv.empty()) { | ||||
state.nHeadersSyncTimeout < std::numeric_limits<int64_t>::max()) { | state.nHeadersSyncTimeout < std::numeric_limits<int64_t>::max()) { | ||||
// Detect whether this is a stalling initial-headers-sync peer | // Detect whether this is a stalling initial-headers-sync peer | ||||
if (pindexBestHeader->GetBlockTime() <= | if (pindexBestHeader->GetBlockTime() <= | ||||
GetAdjustedTime() - 24 * 60 * 60) { | GetAdjustedTime() - 24 * 60 * 60) { | ||||
if (count_microseconds(current_time) > | if (count_microseconds(current_time) > | ||||
state.nHeadersSyncTimeout && | state.nHeadersSyncTimeout && | ||||
nSyncStarted == 1 && | nSyncStarted == 1 && | ||||
(nPreferredDownload - state.fPreferredDownload >= 1)) { | (nPreferredDownload - state.fPreferredDownload >= 1)) { | ||||
// Disconnect a (non-whitelisted) peer if it is our only | // Disconnect a peer (without the noban permission) if it | ||||
// sync peer, and we have others we could be using instead. | // is our only sync peer, and we have others we could be | ||||
// using instead. | |||||
// Note: If all our peers are inbound, then we won't | // Note: If all our peers are inbound, then we won't | ||||
// disconnect our sync peer for stalling; we have bigger | // disconnect our sync peer for stalling; we have bigger | ||||
// problems if we can't get any outbound peers. | // problems if we can't get any outbound peers. | ||||
if (!pto->HasPermission(PF_NOBAN)) { | if (!pto->HasPermission(PF_NOBAN)) { | ||||
LogPrintf("Timeout downloading headers from peer=%d, " | LogPrintf("Timeout downloading headers from peer=%d, " | ||||
"disconnecting\n", | "disconnecting\n", | ||||
pto->GetId()); | pto->GetId()); | ||||
pto->fDisconnect = true; | pto->fDisconnect = true; | ||||
return true; | return true; | ||||
} else { | } else { | ||||
LogPrintf( | LogPrintf("Timeout downloading headers from noban " | ||||
"Timeout downloading headers from whitelisted " | |||||
"peer=%d, not disconnecting\n", | "peer=%d, not disconnecting\n", | ||||
pto->GetId()); | pto->GetId()); | ||||
// Reset the headers sync state so that we have a chance | // Reset the headers sync state so that we have a chance | ||||
// to try downloading from a different peer. Note: this | // to try downloading from a different peer. Note: this | ||||
// will also result in at least one more getheaders | // will also result in at least one more getheaders | ||||
// message to be sent to this peer (eventually). | // message to be sent to this peer (eventually). | ||||
state.fSyncStarted = false; | state.fSyncStarted = false; | ||||
nSyncStarted--; | nSyncStarted--; | ||||
state.nHeadersSyncTimeout = 0; | state.nHeadersSyncTimeout = 0; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 199 Lines • Show Last 20 Lines |