aboutsummaryrefslogtreecommitdiff
path: root/src/net_processing.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net_processing.cpp')
-rw-r--r--src/net_processing.cpp56
1 files changed, 46 insertions, 10 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index b81119bdd6..1d69975f55 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -21,6 +21,7 @@
#include <node/blockstorage.h>
#include <policy/fees.h>
#include <policy/policy.h>
+#include <policy/settings.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <random.h>
@@ -459,7 +460,7 @@ struct CNodeState {
class PeerManagerImpl final : public PeerManager
{
public:
- PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, AddrMan& addrman,
+ PeerManagerImpl(CConnman& connman, AddrMan& addrman,
BanMan* banman, ChainstateManager& chainman,
CTxMemPool& pool, bool ignore_incoming_txs);
@@ -1587,17 +1588,17 @@ std::optional<std::string> PeerManagerImpl::FetchBlock(NodeId peer_id, const CBl
return std::nullopt;
}
-std::unique_ptr<PeerManager> PeerManager::make(const CChainParams& chainparams, CConnman& connman, AddrMan& addrman,
+std::unique_ptr<PeerManager> PeerManager::make(CConnman& connman, AddrMan& addrman,
BanMan* banman, ChainstateManager& chainman,
CTxMemPool& pool, bool ignore_incoming_txs)
{
- return std::make_unique<PeerManagerImpl>(chainparams, connman, addrman, banman, chainman, pool, ignore_incoming_txs);
+ return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, ignore_incoming_txs);
}
-PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, AddrMan& addrman,
+PeerManagerImpl::PeerManagerImpl(CConnman& connman, AddrMan& addrman,
BanMan* banman, ChainstateManager& chainman,
CTxMemPool& pool, bool ignore_incoming_txs)
- : m_chainparams(chainparams),
+ : m_chainparams(chainman.GetParams()),
m_connman(connman),
m_addrman(addrman),
m_banman(banman),
@@ -3300,9 +3301,23 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
return;
}
+ if (fImporting || fReindex) {
+ LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d while importing/reindexing\n", pfrom.GetId());
+ return;
+ }
+
LOCK(cs_main);
- if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && !pfrom.HasPermission(NetPermissionFlags::Download)) {
- LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom.GetId());
+
+ // 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 seen the
+ // checkpointed chain would cause that peer to disconnect us. Requiring
+ // that our chainwork exceed nMinimumChainWork is a protection against
+ // being fed a bogus chain when we started up for the first time and
+ // getting partitioned off the honest network for serving that chain to
+ // others.
+ if (m_chainman.ActiveTip() == nullptr ||
+ (m_chainman.ActiveTip()->nChainWork < nMinimumChainWork && !pfrom.HasPermission(NetPermissionFlags::Download))) {
+ LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because active chain has too little work\n", pfrom.GetId());
return;
}
@@ -4703,10 +4718,31 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
if (m_chainman.m_best_header == nullptr) {
m_chainman.m_best_header = m_chainman.ActiveChain().Tip();
}
- bool fFetch = state.fPreferredDownload || (m_num_preferred_download_peers == 0 && !pto->fClient && !pto->IsAddrFetchConn()); // Download if this is a nice peer, or we have no nice peers and this one might do.
+
+ // Determine whether we might try initial headers sync or parallel
+ // block download from this peer -- this mostly affects behavior while
+ // in IBD (once out of IBD, we sync from all peers).
+ bool sync_blocks_and_headers_from_peer = false;
+ if (state.fPreferredDownload) {
+ sync_blocks_and_headers_from_peer = true;
+ } else if (!pto->fClient && !pto->IsAddrFetchConn()) {
+ // Typically this is an inbound peer. If we don't have any outbound
+ // peers, or if we aren't downloading any blocks from such peers,
+ // then allow block downloads from this peer, too.
+ // We prefer downloading blocks from outbound peers to avoid
+ // putting undue load on (say) some home user who is just making
+ // outbound connections to the network, but if our only source of
+ // the latest blocks is from an inbound peer, we have to be sure to
+ // eventually download it (and not just wait indefinitely for an
+ // outbound peer to have it).
+ if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
+ sync_blocks_and_headers_from_peer = true;
+ }
+ }
+
if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) {
// Only actively request headers from a single peer, unless we're close to today.
- if ((nSyncStarted == 0 && fFetch) || m_chainman.m_best_header->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
+ if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
state.fSyncStarted = true;
state.m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE +
(
@@ -5079,7 +5115,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// Message: getdata (blocks)
//
std::vector<CInv> vGetData;
- if (!pto->fClient && ((fFetch && !pto->m_limited_node) || !m_chainman.ActiveChainstate().IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
+ if (!pto->fClient && ((sync_blocks_and_headers_from_peer && !pto->m_limited_node) || !m_chainman.ActiveChainstate().IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
std::vector<const CBlockIndex*> vToDownload;
NodeId staller = -1;
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);