net: Disallow invalid HeadersSyncState due to lagging clock #35351

pull hodlinator wants to merge 3 commits into bitcoin:master from hodlinator:pr/35208_alt changing 5 files +50 −14
  1. hodlinator commented at 7:56 PM on May 21, 2026: contributor

    Problem

    Headers presync computes m_max_commitments from the elapsed time since the chain-start MTP plus MAX_FUTURE_BLOCK_TIME. When the local system clock is more than MAX_FUTURE_BLOCK_TIME behind the chain-start MTP, that elapsed value is negative, but it is used in arithmetic assigned to the unsigned commitment cap. This can turn the intended zero bound into a large cap, letting low-work headers presync continue instead of aborting when a reasonable commitment cap would have been exceeded.

    Fix

    Instead of allowing an invalid HeadersSyncState object to be created, throw an exception from the constructor.

    Typically, the node will detect that the system clock is set too far in the past when comparing it to the chain tip during chain state loading and shut down before we start syncing headers. So in practice this is very unlikely to make a difference (might be possible if the system clock jumps backwards after we loaded the chain state).

    Commits

    • A regression test pinning the current behavior.
    • The fix, along with the corresponding test change.
    • The headers_sync_state fuzz target also now allows the same clock-skew case instead of always choosing a time at or after the chain-start MTP.

    Replaces #35208 which was clamping m_max_commitments to zero and then letting the HeadersSyncState consume headers until the block height either reached the the next commitment_period point and aborted, or reached the minimum work threshold and succeeded (possible when having been offline for >144 blocks).

  2. test: Cover future chain-start MTP boundary in headers presync
    When the local clock sits more than `MAX_FUTURE_BLOCK_TIME` behind the chain-start MTP, the elapsed value used to derive `m_max_commitments` is negative.
    The later division by the unsigned commitment period converts that negative value to a large unsigned bound.
    Presync ends up with A LOT of commitment slots, whereas it should abort.
    
    Pin that pre-fix behavior in a regression test that the subsequent fix will alter.
    
    Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
    b0a2c0daf5
  3. net: Throw exception from HeadersSyncState when system clock is behind start block MTP
    We should not proceed syncing headers from peers when the local system clock is incorrectly set.
    
    A node with a system clock set too far back will typically fail early during startup when the chainstate detects the tip to be too far in the future. This means that in practice we don't expect the failure to ever happen in net_processing.cpp.
    One can provoke the std::abort() in net_processing.cpp to happen through adding a call to SetMockTime(1) right before creating the HeadersSyncState.
    
    Issue discovered by: Lőrinc <pap.lorinc@gmail.com>
    db9c704117
  4. fuzz: Make headerssync target also cover HeadersSyncState::SystemClockError
    Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
    2cb8aa05be
  5. DrahtBot added the label P2P on May 21, 2026
  6. DrahtBot commented at 7:56 PM on May 21, 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/35351.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK w0xlt

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35114 (test: NodeClockContext follow-ups by seduless)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible places where comparison-specific test macros should replace generic comparisons:

    • [src/test/headers_sync_chainwork_tests.cpp] BOOST_CHECK_THROW(CreateState(), HeadersSyncState::SystemClockError); -> Consider BOOST_CHECK_EXCEPTION with a predicate that verifies the exception message, so the test checks the specific failure reason instead of only the exception type.

    <sup>2026-05-21 19:57:01</sup>

  7. DrahtBot added the label CI failed on May 21, 2026
  8. DrahtBot removed the label CI failed on May 22, 2026
  9. w0xlt commented at 2:01 PM on May 22, 2026: contributor

    Concept ACK


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-05-22 20:51 UTC

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