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 316 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
std::map<TxId, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans); | std::map<TxId, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans); | ||||
void EraseOrphansFor(NodeId peer); | void EraseOrphansFor(NodeId peer); | ||||
// Internal stuff | // Internal stuff | ||||
namespace { | namespace { | ||||
/** | /** | ||||
* Blocks that are in flight, and that are in the queue to be downloaded. | |||||
*/ | |||||
struct QueuedBlock { | |||||
BlockHash hash; | |||||
//! Optional. | |||||
const CBlockIndex *pindex; | |||||
//! Whether this block has validated headers at the time of request. | |||||
bool fValidatedHeaders; | |||||
//! Optional, used for CMPCTBLOCK downloads | |||||
std::unique_ptr<PartiallyDownloadedBlock> partialBlock; | |||||
}; | |||||
/** | |||||
* Data structure for an individual peer. This struct is not protected by | * Data structure for an individual peer. This struct is not protected by | ||||
* cs_main since it does not contain validation-critical data. | * cs_main since it does not contain validation-critical data. | ||||
* | * | ||||
* Memory is owned by shared pointers and this object is destructed when | * Memory is owned by shared pointers and this object is destructed when | ||||
* the refcount drops to zero. | * the refcount drops to zero. | ||||
* | * | ||||
* Mutexes inside this struct must not be held when locking m_peer_mutex. | * Mutexes inside this struct must not be held when locking m_peer_mutex. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 402 Lines • ▼ Show 20 Lines | private: | ||||
* We use this to avoid requesting transactions that have already been | * We use this to avoid requesting transactions that have already been | ||||
* confirmed. | * confirmed. | ||||
*/ | */ | ||||
Mutex m_recent_confirmed_transactions_mutex; | Mutex m_recent_confirmed_transactions_mutex; | ||||
std::unique_ptr<CRollingBloomFilter> m_recent_confirmed_transactions | std::unique_ptr<CRollingBloomFilter> m_recent_confirmed_transactions | ||||
GUARDED_BY(m_recent_confirmed_transactions_mutex); | GUARDED_BY(m_recent_confirmed_transactions_mutex); | ||||
/** | /** | ||||
* Returns a bool indicating whether we requested this block. | |||||
* Also used if a block was /not/ received and timed out or started with | |||||
* another peer | |||||
*/ | |||||
bool MarkBlockAsReceived(const BlockHash &hash) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
/** | |||||
* Mark a block as in flight | |||||
* Returns false, still setting pit, if the block was already in flight from | |||||
* the same peer pit will only be valid as long as the same cs_main lock is | |||||
* being held | |||||
*/ | |||||
bool MarkBlockAsInFlight(const Config &config, NodeId nodeid, | |||||
const BlockHash &hash, | |||||
const CBlockIndex *pindex = nullptr, | |||||
std::list<QueuedBlock>::iterator **pit = nullptr) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool TipMayBeStale() EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
/** | |||||
* Update pindexLastCommonBlock and add not-in-flight missing successors to | |||||
* vBlocks, until it has at most count entries. | |||||
*/ | |||||
void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, | |||||
std::vector<const CBlockIndex *> &vBlocks, | |||||
NodeId &nodeStaller) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
std::map<BlockHash, std::pair<NodeId, std::list<QueuedBlock>::iterator>> | |||||
mapBlocksInFlight GUARDED_BY(cs_main); | |||||
/** When our tip was last updated. */ | |||||
std::atomic<int64_t> m_last_tip_update{0}; | |||||
/** | |||||
* Checks if address relay is permitted with peer. If needed, initializes | * Checks if address relay is permitted with peer. If needed, initializes | ||||
* the m_addr_known bloom filter and sets m_addr_relay_enabled to true. | * the m_addr_known bloom filter and sets m_addr_relay_enabled to true. | ||||
* | * | ||||
* @return True if address relay is enabled with peer | * @return True if address relay is enabled with peer | ||||
* False if address relay is disallowed | * False if address relay is disallowed | ||||
*/ | */ | ||||
bool SetupAddressRelay(CNode &node, Peer &peer); | bool SetupAddressRelay(CNode &node, Peer &peer); | ||||
}; | }; | ||||
Show All 9 Lines | |||||
* | * | ||||
* Decreasing the false positive rate is fairly cheap, so we pick one in a | * Decreasing the false positive rate is fairly cheap, so we pick one in a | ||||
* million to make it highly unlikely for users to have issues with this filter. | * million to make it highly unlikely for users to have issues with this filter. | ||||
*/ | */ | ||||
Mutex cs_rejectedProofs; | Mutex cs_rejectedProofs; | ||||
std::unique_ptr<CRollingBloomFilter> | std::unique_ptr<CRollingBloomFilter> | ||||
rejectedProofs GUARDED_BY(cs_rejectedProofs); | rejectedProofs GUARDED_BY(cs_rejectedProofs); | ||||
/** | |||||
* Blocks that are in flight, and that are in the queue to be downloaded. | |||||
*/ | |||||
struct QueuedBlock { | |||||
BlockHash hash; | |||||
//! Optional. | |||||
const CBlockIndex *pindex; | |||||
//! Whether this block has validated headers at the time of request. | |||||
bool fValidatedHeaders; | |||||
//! Optional, used for CMPCTBLOCK downloads | |||||
std::unique_ptr<PartiallyDownloadedBlock> partialBlock; | |||||
}; | |||||
std::map<BlockHash, std::pair<NodeId, std::list<QueuedBlock>::iterator>> | |||||
mapBlocksInFlight GUARDED_BY(cs_main); | |||||
/** Stack of nodes which we have set to announce using compact blocks */ | /** Stack of nodes which we have set to announce using compact blocks */ | ||||
std::list<NodeId> lNodesAnnouncingHeaderAndIDs GUARDED_BY(cs_main); | std::list<NodeId> lNodesAnnouncingHeaderAndIDs GUARDED_BY(cs_main); | ||||
/** Number of preferable block download peers. */ | /** Number of preferable block download peers. */ | ||||
int nPreferredDownload GUARDED_BY(cs_main) = 0; | int nPreferredDownload GUARDED_BY(cs_main) = 0; | ||||
/** Number of peers from which we're downloading blocks. */ | /** Number of peers from which we're downloading blocks. */ | ||||
int nPeersWithValidatedDownloads GUARDED_BY(cs_main) = 0; | int nPeersWithValidatedDownloads GUARDED_BY(cs_main) = 0; | ||||
/** When our tip was last updated. */ | |||||
std::atomic<int64_t> g_last_tip_update(0); | |||||
/** Relay map. */ | /** Relay map. */ | ||||
typedef std::map<uint256, CTransactionRef> MapRelay; | typedef std::map<uint256, CTransactionRef> MapRelay; | ||||
MapRelay mapRelay GUARDED_BY(cs_main); | MapRelay mapRelay GUARDED_BY(cs_main); | ||||
/** | /** | ||||
* Expiration-time ordered list of (expire time, relay map entry) pairs, | * Expiration-time ordered list of (expire time, relay map entry) pairs, | ||||
* protected by cs_main). | * protected by cs_main). | ||||
*/ | */ | ||||
std::deque<std::pair<std::chrono::microseconds, MapRelay::iterator>> | std::deque<std::pair<std::chrono::microseconds, MapRelay::iterator>> | ||||
▲ Show 20 Lines • Show All 223 Lines • ▼ Show 20 Lines | static void UpdatePreferredDownload(const CNode &node, CNodeState *state) | ||||
// Whether this node should be marked as a preferred download node. | // Whether this node should be marked as a preferred download node. | ||||
state->fPreferredDownload = | state->fPreferredDownload = | ||||
(!node.IsInboundConn() || node.HasPermission(PF_NOBAN)) && | (!node.IsInboundConn() || node.HasPermission(PF_NOBAN)) && | ||||
!node.IsAddrFetchConn() && !node.fClient; | !node.IsAddrFetchConn() && !node.fClient; | ||||
nPreferredDownload += state->fPreferredDownload; | nPreferredDownload += state->fPreferredDownload; | ||||
} | } | ||||
// Returns a bool indicating whether we requested this block. | bool PeerManagerImpl::MarkBlockAsReceived(const BlockHash &hash) | ||||
// Also used if a block was /not/ received and timed out or started with another | |||||
// peer. | |||||
static bool MarkBlockAsReceived(const BlockHash &hash) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
std::map<BlockHash, | std::map<BlockHash, | ||||
std::pair<NodeId, std::list<QueuedBlock>::iterator>>::iterator | std::pair<NodeId, std::list<QueuedBlock>::iterator>>::iterator | ||||
itInFlight = mapBlocksInFlight.find(hash); | itInFlight = mapBlocksInFlight.find(hash); | ||||
if (itInFlight != mapBlocksInFlight.end()) { | if (itInFlight != mapBlocksInFlight.end()) { | ||||
CNodeState *state = State(itInFlight->second.first); | CNodeState *state = State(itInFlight->second.first); | ||||
assert(state != nullptr); | assert(state != nullptr); | ||||
state->nBlocksInFlightValidHeaders -= | state->nBlocksInFlightValidHeaders -= | ||||
Show All 15 Lines | if (itInFlight != mapBlocksInFlight.end()) { | ||||
state->m_stalling_since = 0us; | state->m_stalling_since = 0us; | ||||
mapBlocksInFlight.erase(itInFlight); | mapBlocksInFlight.erase(itInFlight); | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
// returns false, still setting pit, if the block was already in flight from the | bool PeerManagerImpl::MarkBlockAsInFlight( | ||||
// same peer | const Config &config, NodeId nodeid, const BlockHash &hash, | ||||
// pit will only be valid as long as the same cs_main lock is being held. | const CBlockIndex *pindex, std::list<QueuedBlock>::iterator **pit) | ||||
static bool | |||||
MarkBlockAsInFlight(const Config &config, CTxMemPool &mempool, NodeId nodeid, | |||||
const BlockHash &hash, | |||||
const Consensus::Params &consensusParams, | |||||
const CBlockIndex *pindex = nullptr, | |||||
std::list<QueuedBlock>::iterator **pit = nullptr) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
CNodeState *state = State(nodeid); | CNodeState *state = State(nodeid); | ||||
assert(state != nullptr); | assert(state != nullptr); | ||||
// Short-circuit most stuff in case it is from the same node. | // Short-circuit most stuff in case it is from the same node. | ||||
std::map<BlockHash, | std::map<BlockHash, | ||||
std::pair<NodeId, std::list<QueuedBlock>::iterator>>::iterator | std::pair<NodeId, std::list<QueuedBlock>::iterator>>::iterator | ||||
itInFlight = mapBlocksInFlight.find(hash); | itInFlight = mapBlocksInFlight.find(hash); | ||||
if (itInFlight != mapBlocksInFlight.end() && | if (itInFlight != mapBlocksInFlight.end() && | ||||
itInFlight->second.first == nodeid) { | itInFlight->second.first == nodeid) { | ||||
if (pit) { | if (pit) { | ||||
*pit = &itInFlight->second.second; | *pit = &itInFlight->second.second; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
// Make sure it's not listed somewhere already. | // Make sure it's not listed somewhere already. | ||||
MarkBlockAsReceived(hash); | MarkBlockAsReceived(hash); | ||||
std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert( | std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert( | ||||
state->vBlocksInFlight.end(), | state->vBlocksInFlight.end(), | ||||
{hash, pindex, pindex != nullptr, | {hash, pindex, pindex != nullptr, | ||||
std::unique_ptr<PartiallyDownloadedBlock>( | std::unique_ptr<PartiallyDownloadedBlock>( | ||||
pit ? new PartiallyDownloadedBlock(config, &mempool) : nullptr)}); | pit ? new PartiallyDownloadedBlock(config, &m_mempool) | ||||
: nullptr)}); | |||||
state->nBlocksInFlight++; | state->nBlocksInFlight++; | ||||
state->nBlocksInFlightValidHeaders += it->fValidatedHeaders; | state->nBlocksInFlightValidHeaders += it->fValidatedHeaders; | ||||
if (state->nBlocksInFlight == 1) { | if (state->nBlocksInFlight == 1) { | ||||
// We're starting a block download (batch) from this peer. | // We're starting a block download (batch) from this peer. | ||||
state->m_downloading_since = GetTime<std::chrono::microseconds>(); | state->m_downloading_since = GetTime<std::chrono::microseconds>(); | ||||
} | } | ||||
if (state->nBlocksInFlightValidHeaders == 1 && pindex != nullptr) { | if (state->nBlocksInFlightValidHeaders == 1 && pindex != nullptr) { | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | connman.ForNode(nodeid, [&connman](CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED( | ||||
nCMPCTBLOCKVersion)); | nCMPCTBLOCKVersion)); | ||||
// save BIP152 bandwidth state: we select peer to be high-bandwidth | // save BIP152 bandwidth state: we select peer to be high-bandwidth | ||||
pfrom->m_bip152_highbandwidth_to = true; | pfrom->m_bip152_highbandwidth_to = true; | ||||
lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId()); | lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId()); | ||||
return true; | return true; | ||||
}); | }); | ||||
} | } | ||||
static bool TipMayBeStale(const Consensus::Params &consensusParams) | bool PeerManagerImpl::TipMayBeStale() { | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (g_last_tip_update == 0) { | const Consensus::Params &consensusParams = m_chainparams.GetConsensus(); | ||||
g_last_tip_update = GetTime(); | if (m_last_tip_update == 0) { | ||||
m_last_tip_update = GetTime(); | |||||
} | } | ||||
return g_last_tip_update < | return m_last_tip_update < | ||||
GetTime() - consensusParams.nPowTargetSpacing * 3 && | GetTime() - consensusParams.nPowTargetSpacing * 3 && | ||||
mapBlocksInFlight.empty(); | mapBlocksInFlight.empty(); | ||||
} | } | ||||
static bool CanDirectFetch(const Consensus::Params &consensusParams) | static bool CanDirectFetch(const Consensus::Params &consensusParams) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
return ::ChainActive().Tip()->GetBlockTime() > | return ::ChainActive().Tip()->GetBlockTime() > | ||||
GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20; | GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20; | ||||
} | } | ||||
static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) | static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
if (state->pindexBestKnownBlock && | if (state->pindexBestKnownBlock && | ||||
pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight)) { | pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight)) { | ||||
return true; | return true; | ||||
} | } | ||||
if (state->pindexBestHeaderSent && | if (state->pindexBestHeaderSent && | ||||
pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight)) { | pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight)) { | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
/** | void PeerManagerImpl::FindNextBlocksToDownload( | ||||
* Update pindexLastCommonBlock and add not-in-flight missing successors to | NodeId nodeid, unsigned int count, | ||||
* vBlocks, until it has at most count entries. | std::vector<const CBlockIndex *> &vBlocks, NodeId &nodeStaller) | ||||
*/ | |||||
static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, | |||||
std::vector<const CBlockIndex *> &vBlocks, | |||||
NodeId &nodeStaller, | |||||
const Consensus::Params &consensusParams) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
if (count == 0) { | if (count == 0) { | ||||
return; | return; | ||||
} | } | ||||
vBlocks.reserve(vBlocks.size() + count); | vBlocks.reserve(vBlocks.size() + count); | ||||
CNodeState *state = State(nodeid); | CNodeState *state = State(nodeid); | ||||
assert(state != nullptr); | assert(state != nullptr); | ||||
▲ Show 20 Lines • Show All 859 Lines • ▼ Show 20 Lines | const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex) { | ||||
for (const auto &orphanId : vOrphanErase) { | for (const auto &orphanId : vOrphanErase) { | ||||
nErased += EraseOrphanTx(orphanId); | nErased += EraseOrphanTx(orphanId); | ||||
} | } | ||||
LogPrint(BCLog::MEMPOOL, | LogPrint(BCLog::MEMPOOL, | ||||
"Erased %d orphan tx included or conflicted by block\n", | "Erased %d orphan tx included or conflicted by block\n", | ||||
nErased); | nErased); | ||||
} | } | ||||
g_last_tip_update = GetTime(); | m_last_tip_update = GetTime(); | ||||
} | } | ||||
{ | { | ||||
LOCK(m_recent_confirmed_transactions_mutex); | LOCK(m_recent_confirmed_transactions_mutex); | ||||
for (const CTransactionRef &ptx : pblock->vtx) { | for (const CTransactionRef &ptx : pblock->vtx) { | ||||
m_recent_confirmed_transactions->insert(ptx->GetId()); | m_recent_confirmed_transactions->insert(ptx->GetId()); | ||||
} | } | ||||
} | } | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 851 Lines • ▼ Show 20 Lines | if (!m_chainman.ProcessNewBlockHeaders(config, headers, state, | ||||
// Download as much as possible, from earliest to latest. | // Download as much as possible, from earliest to latest. | ||||
for (const CBlockIndex *pindex : reverse_iterate(vToFetch)) { | for (const CBlockIndex *pindex : reverse_iterate(vToFetch)) { | ||||
if (nodestate->nBlocksInFlight >= | if (nodestate->nBlocksInFlight >= | ||||
MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | ||||
// Can't download any more from this peer | // Can't download any more from this peer | ||||
break; | break; | ||||
} | } | ||||
vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); | vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); | ||||
MarkBlockAsInFlight(config, m_mempool, pfrom.GetId(), | MarkBlockAsInFlight(config, pfrom.GetId(), | ||||
pindex->GetBlockHash(), | pindex->GetBlockHash(), pindex); | ||||
m_chainparams.GetConsensus(), pindex); | |||||
LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n", | LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n", | ||||
pindex->GetBlockHash().ToString(), pfrom.GetId()); | pindex->GetBlockHash().ToString(), pfrom.GetId()); | ||||
} | } | ||||
if (vGetData.size() > 1) { | if (vGetData.size() > 1) { | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"Downloading blocks toward %s (%d) via headers " | "Downloading blocks toward %s (%d) via headers " | ||||
"direct fetch\n", | "direct fetch\n", | ||||
pindexLast->GetBlockHash().ToString(), | pindexLast->GetBlockHash().ToString(), | ||||
▲ Show 20 Lines • Show All 1,638 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::CMPCTBLOCK) { | ||||
// We want to be a bit conservative just to be extra careful about | // We want to be a bit conservative just to be extra careful about | ||||
// DoS possibilities in compact block processing... | // DoS possibilities in compact block processing... | ||||
if (pindex->nHeight <= ::ChainActive().Height() + 2) { | if (pindex->nHeight <= ::ChainActive().Height() + 2) { | ||||
if ((!fAlreadyInFlight && nodestate->nBlocksInFlight < | if ((!fAlreadyInFlight && nodestate->nBlocksInFlight < | ||||
MAX_BLOCKS_IN_TRANSIT_PER_PEER) || | MAX_BLOCKS_IN_TRANSIT_PER_PEER) || | ||||
(fAlreadyInFlight && | (fAlreadyInFlight && | ||||
blockInFlightIt->second.first == pfrom.GetId())) { | blockInFlightIt->second.first == pfrom.GetId())) { | ||||
std::list<QueuedBlock>::iterator *queuedBlockIt = nullptr; | std::list<QueuedBlock>::iterator *queuedBlockIt = nullptr; | ||||
if (!MarkBlockAsInFlight(config, m_mempool, pfrom.GetId(), | if (!MarkBlockAsInFlight(config, pfrom.GetId(), | ||||
pindex->GetBlockHash(), | pindex->GetBlockHash(), pindex, | ||||
m_chainparams.GetConsensus(), | &queuedBlockIt)) { | ||||
pindex, &queuedBlockIt)) { | |||||
if (!(*queuedBlockIt)->partialBlock) { | if (!(*queuedBlockIt)->partialBlock) { | ||||
(*queuedBlockIt) | (*queuedBlockIt) | ||||
->partialBlock.reset( | ->partialBlock.reset( | ||||
new PartiallyDownloadedBlock(config, | new PartiallyDownloadedBlock(config, | ||||
&m_mempool)); | &m_mempool)); | ||||
} else { | } else { | ||||
// The block was already in flight using compact | // The block was already in flight using compact | ||||
// blocks from the same peer. | // blocks from the same peer. | ||||
▲ Show 20 Lines • Show All 1,404 Lines • ▼ Show 20 Lines | void PeerManagerImpl::CheckForStaleTipAndEvictPeers() { | ||||
int64_t time_in_seconds = GetTime(); | int64_t time_in_seconds = GetTime(); | ||||
EvictExtraOutboundPeers(std::chrono::seconds{time_in_seconds}); | EvictExtraOutboundPeers(std::chrono::seconds{time_in_seconds}); | ||||
if (time_in_seconds > m_stale_tip_check_time) { | if (time_in_seconds > m_stale_tip_check_time) { | ||||
// Check whether our tip is stale, and if so, allow using an extra | // Check whether our tip is stale, and if so, allow using an extra | ||||
// outbound peer. | // outbound peer. | ||||
if (!fImporting && !fReindex && m_connman.GetNetworkActive() && | if (!fImporting && !fReindex && m_connman.GetNetworkActive() && | ||||
m_connman.GetUseAddrmanOutgoing() && | m_connman.GetUseAddrmanOutgoing() && TipMayBeStale()) { | ||||
TipMayBeStale(m_chainparams.GetConsensus())) { | |||||
LogPrintf("Potential stale tip detected, will try using extra " | LogPrintf("Potential stale tip detected, will try using extra " | ||||
"outbound peer (last tip update: %d seconds ago)\n", | "outbound peer (last tip update: %d seconds ago)\n", | ||||
time_in_seconds - g_last_tip_update); | time_in_seconds - m_last_tip_update); | ||||
m_connman.SetTryNewOutboundPeer(true); | m_connman.SetTryNewOutboundPeer(true); | ||||
} else if (m_connman.GetTryNewOutboundPeer()) { | } else if (m_connman.GetTryNewOutboundPeer()) { | ||||
m_connman.SetTryNewOutboundPeer(false); | m_connman.SetTryNewOutboundPeer(false); | ||||
} | } | ||||
m_stale_tip_check_time = time_in_seconds + STALE_CHECK_INTERVAL; | m_stale_tip_check_time = time_in_seconds + STALE_CHECK_INTERVAL; | ||||
} | } | ||||
if (!m_initial_sync_finished && | if (!m_initial_sync_finished && | ||||
▲ Show 20 Lines • Show All 746 Lines • ▼ Show 20 Lines | // | ||||
((fFetch && !pto->m_limited_node) || | ((fFetch && !pto->m_limited_node) || | ||||
!::ChainstateActive().IsInitialBlockDownload()) && | !::ChainstateActive().IsInitialBlockDownload()) && | ||||
state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | ||||
std::vector<const CBlockIndex *> vToDownload; | std::vector<const CBlockIndex *> vToDownload; | ||||
NodeId staller = -1; | NodeId staller = -1; | ||||
FindNextBlocksToDownload(pto->GetId(), | FindNextBlocksToDownload(pto->GetId(), | ||||
MAX_BLOCKS_IN_TRANSIT_PER_PEER - | MAX_BLOCKS_IN_TRANSIT_PER_PEER - | ||||
state.nBlocksInFlight, | state.nBlocksInFlight, | ||||
vToDownload, staller, consensusParams); | vToDownload, staller); | ||||
for (const CBlockIndex *pindex : vToDownload) { | for (const CBlockIndex *pindex : vToDownload) { | ||||
vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); | vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); | ||||
MarkBlockAsInFlight(config, m_mempool, pto->GetId(), | MarkBlockAsInFlight(config, pto->GetId(), | ||||
pindex->GetBlockHash(), consensusParams, | pindex->GetBlockHash(), pindex); | ||||
pindex); | |||||
LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", | LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", | ||||
pindex->GetBlockHash().ToString(), pindex->nHeight, | pindex->GetBlockHash().ToString(), pindex->nHeight, | ||||
pto->GetId()); | pto->GetId()); | ||||
} | } | ||||
if (state.nBlocksInFlight == 0 && staller != -1) { | if (state.nBlocksInFlight == 0 && staller != -1) { | ||||
if (State(staller)->m_stalling_since == 0us) { | if (State(staller)->m_stalling_since == 0us) { | ||||
State(staller)->m_stalling_since = current_time; | State(staller)->m_stalling_since = current_time; | ||||
LogPrint(BCLog::NET, "Stall started peer=%d\n", staller); | LogPrint(BCLog::NET, "Stall started peer=%d\n", staller); | ||||
▲ Show 20 Lines • Show All 148 Lines • Show Last 20 Lines |