Init pruned empty chainstate #36680

pull AlleyBo55 wants to merge 2 commits into bitcoin:master from AlleyBo55:init-pruned-empty-chainstate changing 2 files +33 −1
  1. AlleyBo55 commented at 5:20 AM on October 28, 2026: none

    Fixes #29422

    Motivation

    A pruned node can end up with an empty chainstate (the UTXO database) while its block index already records that the genesis block was pruned. In that state the node cannot start: an empty chainstate is rebuilt by connecting blocks from genesis, but the genesis block data is gone, so no tip can ever be connected. On current master the node waits for a chain tip indefinitely and never prints an actionable error. (The assertion failure in getBlockHash() reported in #29422 was against an older version; on master it hangs instead.)

    How the node reaches this state: during a flush, FlushStateToDisk() writes the block index before it writes the coins database. If the process is interrupted between those two writes during the chainstate's first flush, and that flush also prunes block files, the on-disk block index marks the early blocks (including genesis) as no longer stored, while the coins database was never written. An OOM kill during IBD on a low-memory machine is one way to hit this; deleting the chainstate directory of a pruned node produces the same on-disk state.

    Change

    During chainstate initialization, when a chainstate's coins view is empty, check whether the genesis block is known to the block index but has had its block data pruned. If so, return ChainstateLoadStatus::FAILURE instead of continuing into the wait-for-tip path. The existing failure handling then tells the user to restart with -reindex, and the GUI offers its usual reindex prompt.

    Normal startup, a first startup on an empty datadir, and an explicit -reindex are unaffected, because in those cases the genesis block is not marked as pruned.

    The change does not start a reindex automatically, because recovering a pruned node this way means downloading the whole chain again, which should be the user's choice.

    Testing

    feature_reindex_init.py is extended to reproduce the state directly:

    1. Start a node with -fastprune -prune=1.
    2. Generate 400 blocks and prune, so genesis block data is removed.
    3. Stop the node and delete its chainstate directory.
    4. Assert startup fails with the new error instead of hanging.
    5. Allow the suggested reindex and assert the node comes back up at height 0.

    Without the fix, step 4 never returns and the test hits the 60s startup timeout.

    Verification

    Built and tested on macOS arm64 (Apple Clang 17):

    cmake -B build -DENABLE_IPC=OFF
    cmake --build build -j10
    ctest --test-dir build -j4
    python3 build/test/functional/test_runner.py -j10
    

    All runnable unit tests passed (script_assets_tests was skipped, its external test data was not available). The default functional suite passed, as did the extended pruning/index tests (feature_pruning.py, feature_index_prune.py) and the assumeutxo tests. No new compiler warnings.

    Not tested: Linux/Windows CI, the Qt GUI path, the IPC build, and a real OOM interruption (the test constructs the resulting on-disk state rather than triggering an actual OOM).

  2. init: Fail if empty chainstate cannot be rebuilt
    A pruned node whose chainstate database is empty, and whose block index
    says the genesis block has been pruned, never finishes starting up. An
    empty chainstate can only be rebuilt by connecting blocks from genesis,
    but there is no block data left to connect. Init then waits forever for
    a chain tip, without logging why.
    
    This state is reached when the node is killed, for example by the OOM
    killer, during the first flush of its chainstate if that flush also
    prunes block files: FlushStateToDisk() writes the block index, which
    marks the pruned blocks as missing, before it writes the coins
    database. Deleting the chainstate directory of a pruned node leads to
    the same state. The report in #29422 shows an assertion failure in
    getBlockHash() when an index is enabled. Current master hangs instead,
    with or without an index.
    
    Detect this while loading the chainstate and return a FAILURE status.
    The existing handling then tells the user to restart with -reindex, or
    offers to start the reindex in the GUI.
    
    Fixes #29422.
    0cba362e7e
  3. test: Cover pruned node with empty chainstate
    Delete the chainstate directory of a pruned node whose genesis block
    has been pruned. Check that startup then fails with an error asking
    for a reindex, and that the suggested reindex recovers the node.
    
    Without the previous commit, the node never finishes starting up and
    this test times out.
    212e4441b6
  4. DrahtBot commented at 5:21 AM on October 28, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    External sites

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

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

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  5. maflcko commented at 6:36 AM on October 28, 2026: member

    Thx, but LLM output is not accepted if the author can not properly explain, test or could have written the change themselves. Also, LLM generated content is not allowed in comments/communications. See https://github.com/bitcoin/bitcoin/blob/master/doc/AI_POLICY.md

    The bottleneck in this project has always been review and testing, not writing code. Development here is intentionally conservative and slow, and reviewer attention is the scarcest resource we have. LLMs have made this worse, anyone can now prompt them and post their output as PRs. There is an infinite amount plausible looking "improvements" for LLMs to suggest and work on.

    Unless we fully trust LLMs to both write and review code, humans still have to spend time understanding the proposed changes, which incurs a non-zero cost for every opened PR.

    I understand that contributing to this project can be intimidating, and using LLMs may seem tempting, but it really creates more issues for this project than it solves. The best way to help this project, is to review and test changes. You can use LLMs for this, but you shouldn't solely rely on them, or just post their output.

    I am asking you to reconsider whether it's something you genuinely think the project should pursue, independent of what your LLM suggested.

    See https://github.com/bitcoin/bitcoin/blob/master/doc/AI_POLICY.md

  6. maflcko closed this on Oct 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-10-30 15:51 UTC

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