MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / HeadersDirectFetchBlocks

Method HeadersDirectFetchBlocks

src/net_processing.cpp:2872–2931  ·  view source on GitHub ↗

* Given a new headers tip ending in last_header, potentially request blocks towards that tip. * We require that the given tip have at least as much work as our tip, and for * our current tip to be "close to synced" (see CanDirectFetch()). */

Source from the content-addressed store, hash-verified

2870 * our current tip to be "close to synced" (see CanDirectFetch()).
2871 */
2872void PeerManagerImpl::HeadersDirectFetchBlocks(CNode& pfrom, const Peer& peer, const CBlockIndex& last_header)
2873{
2874 LOCK(cs_main);
2875 CNodeState *nodestate = State(pfrom.GetId());
2876
2877 if (CanDirectFetch() && last_header.IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= last_header.nChainWork) {
2878 std::vector<const CBlockIndex*> vToFetch;
2879 const CBlockIndex* pindexWalk{&last_header};
2880 // Calculate all the blocks we'd need to switch to last_header, up to a limit.
2881 while (pindexWalk && !m_chainman.ActiveChain().Contains(*pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
2882 if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
2883 !IsBlockRequested(pindexWalk->GetBlockHash()) &&
2884 (!DeploymentActiveAt(*pindexWalk, m_chainman, Consensus::DEPLOYMENT_SEGWIT) || CanServeWitnesses(peer))) {
2885 // We don't have this block, and it's not yet in flight.
2886 vToFetch.push_back(pindexWalk);
2887 }
2888 pindexWalk = pindexWalk->pprev;
2889 }
2890 // If pindexWalk still isn't on our main chain, we're looking at a
2891 // very large reorg at a time we think we're close to caught up to
2892 // the main chain -- this shouldn't really happen. Bail out on the
2893 // direct fetch and rely on parallel download instead.
2894 // Common ancestor must exist (genesis).
2895 if (!m_chainman.ActiveChain().Contains(*Assert(pindexWalk))) {
2896 LogDebug(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
2897 last_header.GetBlockHash().ToString(),
2898 last_header.nHeight);
2899 } else {
2900 std::vector<CInv> vGetData;
2901 // Download as much as possible, from earliest to latest.
2902 for (const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2903 if (nodestate->vBlocksInFlight.size() >= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
2904 // Can't download any more from this peer
2905 break;
2906 }
2907 uint32_t nFetchFlags = GetFetchFlags(peer);
2908 vGetData.emplace_back(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash());
2909 BlockRequested(pfrom.GetId(), *pindex);
2910 LogDebug(BCLog::NET, "Requesting block %s from peer=%d",
2911 pindex->GetBlockHash().ToString(), pfrom.GetId());
2912 }
2913 if (vGetData.size() > 1) {
2914 LogDebug(BCLog::NET, "Downloading blocks toward %s (%d) via headers direct fetch\n",
2915 last_header.GetBlockHash().ToString(),
2916 last_header.nHeight);
2917 }
2918 if (vGetData.size() > 0) {
2919 if (!m_opts.ignore_incoming_txs &&
2920 nodestate->m_provides_cmpctblocks &&
2921 vGetData.size() == 1 &&
2922 mapBlocksInFlight.size() == 1 &&
2923 last_header.pprev->IsValid(BLOCK_VALID_CHAIN)) {
2924 // In any case, we want to download using a compact block, not a regular one
2925 vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash);
2926 }
2927 MakeAndPushMessage(pfrom, NetMsgType::GETDATA, vGetData);
2928 }
2929 }

Callers

nothing calls this directly

Calls 13

CanServeWitnessesFunction · 0.85
GetIdMethod · 0.80
StateEnum · 0.70
DeploymentActiveAtFunction · 0.70
CInvClass · 0.70
IsValidMethod · 0.45
TipMethod · 0.45
ContainsMethod · 0.45
sizeMethod · 0.45
GetBlockHashMethod · 0.45
push_backMethod · 0.45
ToStringMethod · 0.45

Tested by

no test coverage detected