MCPcopy Create free account
hub / github.com/Bitcoin-ABC/bitcoin-abc / HeadersDirectFetchBlocks

Method HeadersDirectFetchBlocks

src/net_processing.cpp:3982–4045  ·  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

3980 * CanDirectFetch()).
3981 */
3982void PeerManagerImpl::HeadersDirectFetchBlocks(const Config &config,
3983 CNode &pfrom,
3984 const CBlockIndex &last_header) {
3985 LOCK(cs_main);
3986 CNodeState *nodestate = State(pfrom.GetId());
3987
3988 if (CanDirectFetch() && last_header.IsValid(BlockValidity::TREE) &&
3989 m_chainman.ActiveChain().Tip()->nChainWork <= last_header.nChainWork) {
3990 std::vector<const CBlockIndex *> vToFetch;
3991 const CBlockIndex *pindexWalk{&last_header};
3992 // Calculate all the blocks we'd need to switch to last_header, up to
3993 // a limit.
3994 while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) &&
3995 vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
3996 if (!pindexWalk->nStatus.hasData() &&
3997 !IsBlockRequested(pindexWalk->GetBlockHash())) {
3998 // We don't have this block, and it's not yet in flight.
3999 vToFetch.push_back(pindexWalk);
4000 }
4001 pindexWalk = pindexWalk->pprev;
4002 }
4003 // If pindexWalk still isn't on our main chain, we're looking at a
4004 // very large reorg at a time we think we're close to caught up to
4005 // the main chain -- this shouldn't really happen. Bail out on the
4006 // direct fetch and rely on parallel download instead.
4007 if (!m_chainman.ActiveChain().Contains(pindexWalk)) {
4008 LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
4009 last_header.GetBlockHash().ToString(),
4010 last_header.nHeight);
4011 } else {
4012 std::vector<CInv> vGetData;
4013 // Download as much as possible, from earliest to latest.
4014 for (const CBlockIndex *pindex : reverse_iterate(vToFetch)) {
4015 if (nodestate->vBlocksInFlight.size() >=
4016 MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
4017 // Can't download any more from this peer
4018 break;
4019 }
4020 vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
4021 BlockRequested(config, pfrom.GetId(), *pindex);
4022 LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
4023 pindex->GetBlockHash().ToString(), pfrom.GetId());
4024 }
4025 if (vGetData.size() > 1) {
4026 LogPrint(BCLog::NET,
4027 "Downloading blocks toward %s (%d) via headers "
4028 "direct fetch\n",
4029 last_header.GetBlockHash().ToString(),
4030 last_header.nHeight);
4031 }
4032 if (vGetData.size() > 0) {
4033 if (!m_opts.ignore_incoming_txs &&
4034 nodestate->m_provides_cmpctblocks && vGetData.size() == 1 &&
4035 mapBlocksInFlight.size() == 1 &&
4036 last_header.pprev->IsValid(BlockValidity::CHAIN)) {
4037 // In any case, we want to download using a compact
4038 // block, not a regular one.
4039 vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash);

Callers

nothing calls this directly

Calls 12

reverse_iterateFunction · 0.85
TipMethod · 0.80
hasDataMethod · 0.80
StateEnum · 0.70
CInvClass · 0.70
GetIdMethod · 0.45
IsValidMethod · 0.45
ContainsMethod · 0.45
sizeMethod · 0.45
GetBlockHashMethod · 0.45
push_backMethod · 0.45
ToStringMethod · 0.45

Tested by

no test coverage detected