| 1483 | } |
| 1484 | |
| 1485 | void PeerManagerImpl::FindNextBlocks(std::vector<const CBlockIndex*>& vBlocks, const Peer& peer, CNodeState *state, const CBlockIndex *pindexWalk, unsigned int count, int nWindowEnd, const CChain* activeChain, NodeId* nodeStaller) |
| 1486 | { |
| 1487 | std::vector<const CBlockIndex*> vToFetch; |
| 1488 | int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1); |
| 1489 | bool is_limited_peer = IsLimitedPeer(peer); |
| 1490 | NodeId waitingfor = -1; |
| 1491 | while (pindexWalk->nHeight < nMaxHeight) { |
| 1492 | // Read up to 128 (or more, if more blocks than that are needed) successors of pindexWalk (towards |
| 1493 | // pindexBestKnownBlock) into vToFetch. We fetch 128, because CBlockIndex::GetAncestor may be as expensive |
| 1494 | // as iterating over ~100 CBlockIndex* entries anyway. |
| 1495 | int nToFetch = std::min(nMaxHeight - pindexWalk->nHeight, std::max<int>(count - vBlocks.size(), 128)); |
| 1496 | vToFetch.resize(nToFetch); |
| 1497 | pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->nHeight + nToFetch); |
| 1498 | vToFetch[nToFetch - 1] = pindexWalk; |
| 1499 | for (unsigned int i = nToFetch - 1; i > 0; i--) { |
| 1500 | vToFetch[i - 1] = vToFetch[i]->pprev; |
| 1501 | } |
| 1502 | |
| 1503 | // Iterate over those blocks in vToFetch (in forward direction), adding the ones that |
| 1504 | // are not yet downloaded and not in flight to vBlocks. In the meantime, update |
| 1505 | // pindexLastCommonBlock as long as all ancestors are already downloaded, or if it's |
| 1506 | // already part of our chain (and therefore don't need it even if pruned). |
| 1507 | for (const CBlockIndex* pindex : vToFetch) { |
| 1508 | if (!pindex->IsValid(BLOCK_VALID_TREE)) { |
| 1509 | // We consider the chain that this peer is on invalid. |
| 1510 | return; |
| 1511 | } |
| 1512 | |
| 1513 | if (!CanServeWitnesses(peer) && DeploymentActiveAt(*pindex, m_chainman, Consensus::DEPLOYMENT_SEGWIT)) { |
| 1514 | // We wouldn't download this block or its descendants from this peer. |
| 1515 | return; |
| 1516 | } |
| 1517 | |
| 1518 | if (pindex->nStatus & BLOCK_HAVE_DATA || (activeChain && activeChain->Contains(*pindex))) { |
| 1519 | if (activeChain && pindex->HaveNumChainTxs()) { |
| 1520 | state->pindexLastCommonBlock = pindex; |
| 1521 | } |
| 1522 | continue; |
| 1523 | } |
| 1524 | |
| 1525 | // Is block in-flight? |
| 1526 | if (IsBlockRequested(pindex->GetBlockHash())) { |
| 1527 | if (waitingfor == -1) { |
| 1528 | // This is the first already-in-flight block. |
| 1529 | waitingfor = mapBlocksInFlight.lower_bound(pindex->GetBlockHash())->second.first; |
| 1530 | } |
| 1531 | continue; |
| 1532 | } |
| 1533 | |
| 1534 | // The block is not already downloaded, and not yet in flight. |
| 1535 | if (pindex->nHeight > nWindowEnd) { |
| 1536 | // We reached the end of the window. |
| 1537 | if (vBlocks.size() == 0 && waitingfor != peer.m_id) { |
| 1538 | // We aren't able to fetch anything, but we would be if the download window was one larger. |
| 1539 | if (nodeStaller) *nodeStaller = waitingfor; |
| 1540 | } |
| 1541 | return; |
| 1542 | } |
nothing calls this directly
no test coverage detected