Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 1,835 Lines • ▼ Show 20 Lines | void PeerManagerImpl::FindNextBlocksToDownload( | ||||
assert(state != nullptr); | assert(state != nullptr); | ||||
// Make sure pindexBestKnownBlock is up to date, we'll need it. | // Make sure pindexBestKnownBlock is up to date, we'll need it. | ||||
ProcessBlockAvailability(nodeid); | ProcessBlockAvailability(nodeid); | ||||
if (state->pindexBestKnownBlock == nullptr || | if (state->pindexBestKnownBlock == nullptr || | ||||
state->pindexBestKnownBlock->nChainWork < | state->pindexBestKnownBlock->nChainWork < | ||||
m_chainman.ActiveChain().Tip()->nChainWork || | m_chainman.ActiveChain().Tip()->nChainWork || | ||||
state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) { | state->pindexBestKnownBlock->nChainWork < | ||||
m_chainman.MinimumChainWork()) { | |||||
// This peer has nothing interesting. | // This peer has nothing interesting. | ||||
return; | return; | ||||
} | } | ||||
if (state->pindexLastCommonBlock == nullptr) { | if (state->pindexLastCommonBlock == nullptr) { | ||||
// Bootstrap quickly by guessing a parent of our best tip is the forking | // Bootstrap quickly by guessing a parent of our best tip is the forking | ||||
// point. Guessing wrong in either direction is not a problem. | // point. Guessing wrong in either direction is not a problem. | ||||
state->pindexLastCommonBlock = | state->pindexLastCommonBlock = | ||||
▲ Show 20 Lines • Show All 1,565 Lines • ▼ Show 20 Lines | arith_uint256 PeerManagerImpl::GetAntiDoSWorkThreshold() { | ||||
if (m_chainman.ActiveChain().Tip() != nullptr) { | if (m_chainman.ActiveChain().Tip() != nullptr) { | ||||
const CBlockIndex *tip = m_chainman.ActiveChain().Tip(); | const CBlockIndex *tip = m_chainman.ActiveChain().Tip(); | ||||
// Use a 144 block buffer, so that we'll accept headers that fork from | // Use a 144 block buffer, so that we'll accept headers that fork from | ||||
// near our tip. | // near our tip. | ||||
near_chaintip_work = | near_chaintip_work = | ||||
tip->nChainWork - | tip->nChainWork - | ||||
std::min<arith_uint256>(144 * GetBlockProof(*tip), tip->nChainWork); | std::min<arith_uint256>(144 * GetBlockProof(*tip), tip->nChainWork); | ||||
} | } | ||||
return std::max(near_chaintip_work, arith_uint256(nMinimumChainWork)); | return std::max(near_chaintip_work, m_chainman.MinimumChainWork()); | ||||
} | } | ||||
/** | /** | ||||
* Special handling for unconnecting headers that might be part of a block | * Special handling for unconnecting headers that might be part of a block | ||||
* announcement. | * announcement. | ||||
* | * | ||||
* We'll send a getheaders message in response to try to connect the chain. | * We'll send a getheaders message in response to try to connect the chain. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 331 Lines • ▼ Show 20 Lines | void PeerManagerImpl::UpdatePeerStateForReceivedHeaders( | ||||
// If we're in IBD, we want outbound peers that will serve us a useful | // If we're in IBD, we want outbound peers that will serve us a useful | ||||
// chain. Disconnect peers that are on chains with insufficient work. | // chain. Disconnect peers that are on chains with insufficient work. | ||||
if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && | if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && | ||||
!may_have_more_headers) { | !may_have_more_headers) { | ||||
// 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 < nMinimumChainWork) { | nodestate->pindexBestKnownBlock->nChainWork < | ||||
m_chainman.MinimumChainWork()) { | |||||
// 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 it is an outbound disconnection | // us sync -- disconnect if it is an outbound disconnection | ||||
// candidate. | // candidate. | ||||
// Note: We compare their tip to nMinimumChainWork (rather than | // Note: We compare their tip to the minimum chain work (rather than | ||||
// m_chainman.ActiveChain().Tip()) because we won't start block | // m_chainman.ActiveChain().Tip()) because we won't start block | ||||
// download until we have a headers chain that has at least | // download until we have a headers chain that has at least | ||||
// nMinimumChainWork, even if a peer has a chain past our tip, | // the minimum chain work, 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", | ||||
pfrom.GetId()); | pfrom.GetId()); | ||||
pfrom.fDisconnect = true; | pfrom.fDisconnect = true; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,374 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::GETHEADERS) { | ||||
return; | return; | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// Note that if we were to be on a chain that forks from the | // Note that if we were to be on a chain that forks from the | ||||
// checkpointed chain, then serving those headers to a peer that has | // checkpointed chain, then serving those headers to a peer that has | ||||
// seen the checkpointed chain would cause that peer to disconnect us. | // seen the checkpointed chain would cause that peer to disconnect us. | ||||
// Requiring that our chainwork exceed nMinimumChainWork is a protection | // Requiring that our chainwork exceed the minimum chainwork is a | ||||
// against being fed a bogus chain when we started up for the first time | // protection against being fed a bogus chain when we started up for | ||||
// and getting partitioned off the honest network for serving that chain | // the first time and getting partitioned off the honest network for | ||||
// to others. | // serving that chain to others. | ||||
if (m_chainman.ActiveTip() == nullptr || | if (m_chainman.ActiveTip() == nullptr || | ||||
(m_chainman.ActiveTip()->nChainWork < nMinimumChainWork && | (m_chainman.ActiveTip()->nChainWork < | ||||
m_chainman.MinimumChainWork() && | |||||
!pfrom.HasPermission(NetPermissionFlags::Download))) { | !pfrom.HasPermission(NetPermissionFlags::Download))) { | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"Ignoring getheaders from peer=%d because active chain " | "Ignoring getheaders from peer=%d because active chain " | ||||
"has too little work; sending empty response\n", | "has too little work; sending empty response\n", | ||||
pfrom.GetId()); | pfrom.GetId()); | ||||
// Just respond with an empty headers message, to tell the peer to | // Just respond with an empty headers message, to tell the peer to | ||||
// go away but not treat us as unresponsive. | // go away but not treat us as unresponsive. | ||||
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::HEADERS, | m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::HEADERS, | ||||
▲ Show 20 Lines • Show All 478 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::CMPCTBLOCK) { | ||||
std::make_pair(pfrom.GetId(), false)); | std::make_pair(pfrom.GetId(), false)); | ||||
} | } | ||||
// Setting force_processing to true means that we bypass some of | // Setting force_processing to true means that we bypass some of | ||||
// our anti-DoS protections in AcceptBlock, which filters | // our anti-DoS protections in AcceptBlock, which filters | ||||
// unrequested blocks that might be trying to waste our resources | // unrequested blocks that might be trying to waste our resources | ||||
// (eg disk space). Because we only try to reconstruct blocks when | // (eg disk space). Because we only try to reconstruct blocks when | ||||
// we're close to caught up (via the CanDirectFetch() requirement | // we're close to caught up (via the CanDirectFetch() requirement | ||||
// above, combined with the behavior of not requesting blocks until | // above, combined with the behavior of not requesting blocks until | ||||
// we have a chain with at least nMinimumChainWork), and we ignore | // we have a chain with at least the minimum chain work), and we | ||||
// compact blocks with less work than our tip, it is safe to treat | // ignore compact blocks with less work than our tip, it is safe to | ||||
// reconstructed compact blocks as having been requested. | // treat reconstructed compact blocks as having been requested. | ||||
ProcessBlock(config, pfrom, pblock, /*force_processing=*/true, | ProcessBlock(config, pfrom, pblock, /*force_processing=*/true, | ||||
/*min_pow_checked=*/true); | /*min_pow_checked=*/true); | ||||
// hold cs_main for CBlockIndex::IsValid() | // hold cs_main for CBlockIndex::IsValid() | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (pindex->IsValid(BlockValidity::TRANSACTIONS)) { | if (pindex->IsValid(BlockValidity::TRANSACTIONS)) { | ||||
// Clear download state for this block, which is in process from | // Clear download state for this block, which is in process from | ||||
// some other peer. We do this after calling. ProcessNewBlock so | // some other peer. We do this after calling. ProcessNewBlock so | ||||
// that a malleated cmpctblock announcement can't be used to | // that a malleated cmpctblock announcement can't be used to | ||||
▲ Show 20 Lines • Show All 1,762 Lines • ▼ Show 20 Lines | void PeerManagerImpl::MaybeSendSendHeaders(CNode &node, Peer &peer) { | ||||
// initial-headers-sync with this peer. Receiving headers announcements for | // initial-headers-sync with this peer. Receiving headers announcements for | ||||
// new blocks while trying to sync their headers chain is problematic, | // new blocks while trying to sync their headers chain is problematic, | ||||
// because of the state tracking done. | // because of the state tracking done. | ||||
if (!peer.m_sent_sendheaders && | if (!peer.m_sent_sendheaders && | ||||
node.GetCommonVersion() >= SENDHEADERS_VERSION) { | node.GetCommonVersion() >= SENDHEADERS_VERSION) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CNodeState &state = *State(node.GetId()); | CNodeState &state = *State(node.GetId()); | ||||
if (state.pindexBestKnownBlock != nullptr && | if (state.pindexBestKnownBlock != nullptr && | ||||
state.pindexBestKnownBlock->nChainWork > nMinimumChainWork) { | state.pindexBestKnownBlock->nChainWork > | ||||
m_chainman.MinimumChainWork()) { | |||||
// Tell our peer we prefer to receive headers rather than inv's | // Tell our peer we prefer to receive headers rather than inv's | ||||
// We send this to non-NODE NETWORK peers as well, because even | // We send this to non-NODE NETWORK peers as well, because even | ||||
// non-NODE NETWORK peers can announce blocks (such as pruning | // non-NODE NETWORK peers can announce blocks (such as pruning | ||||
// nodes) | // nodes) | ||||
m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()) | m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()) | ||||
.Make(NetMsgType::SENDHEADERS)); | .Make(NetMsgType::SENDHEADERS)); | ||||
peer.m_sent_sendheaders = true; | peer.m_sent_sendheaders = true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 897 Lines • Show Last 20 Lines |