net_processing: count presync work in chain sync eviction #36350

pull 0xShadowX wants to merge 1 commits into bitcoin:master from 0xShadowX:fix-presync-chain-sync-eviction changing 2 files +73 −2
  1. 0xShadowX commented at 10:33 PM on September 26, 2026: none

    While our best header is below -minimumchainwork, a peer's headers first go through the PRESYNC phase of HeadersSyncState, and none of them are stored. So pindexBestKnownBlock stays null for the peer we're syncing from, and ConsiderEviction (net_processing.cpp:5504) treats it like an outbound peer that never announced a block:

    1. it starts CHAIN_SYNC_TIMEOUT (20 min)
    2. it sends a getheaders to "verify chain work"
    3. after HEADERS_RESPONSE_TIME it disconnects with Outbound peer has old chain, best known block = <none>

    This happens even though the peer is still sending headers. The presync progress is lost and the next peer starts from scratch.

    On mainnet presync is roughly 480 headers round trips. If that takes more than ~22 minutes (about 2.5 s per round trip, e.g. over slow Tor or I2P), the sync peer gets evicted before presync can finish, and the same thing can happen with the next peer. The chain sync logic is from #11490, presync came later in #25717, and the two were never connected.

    This treats the peer as caught up when the work it has shown so far during presync (GetPresyncWork()) is at least our tip's work, the same way a stored header with enough work already resets the timeout. m_headers_sync_mutex is never held while taking cs_main, so taking it inside ConsiderEviction doesn't create a lock order problem.

    The new test_presync_peer_not_evicted in p2p_headers_sync_with_minchainwork.py restarts a node with -minimumchainwork=0x20000 (65536 headers). An outbound peer then sends it one full headers message per mocked minute for 25 minutes, so presync is still running at the end. On master the peer is disconnected after 24 minutes. With the fix it stays connected and presynced_headers keeps going up. p2p_outbound_eviction.py, p2p_eviction.py and feature_minchainwork.py still pass.

  2. net_processing: count presync work in chain sync eviction
    While the node's best header has less work than -minimumchainwork, a
    peer's headers go through the PRESYNC phase first, and none of them are
    stored. pindexBestKnownBlock stays null for that peer, so
    ConsiderEviction treats the sync peer like an outbound peer that never
    announced anything: it starts the CHAIN_SYNC_TIMEOUT, then disconnects
    it with "Outbound peer has old chain" after about 22 minutes, even
    though the peer is still delivering headers. Presync progress is lost,
    and the next sync peer starts over.
    
    On mainnet presync takes about 480 round trips, so this hits when
    headers download is slow (e.g. slow Tor or I2P links).
    
    Treat a peer as caught up when the work it has shown during presync is
    at least our tip's work.
    34ef37a550
  3. DrahtBot commented at 10:33 PM on September 26, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/36350.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process. A summary of reviews will appear here.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. maflcko added the label P2P on Sep 28, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-09-28 10:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me