rest: don't log an error for /spenttxouts on a block without undo data #36619

pull kriss39 wants to merge 1 commits into bitcoin:master from kriss39:fix-rest-spenttxouts-no-undo changing 2 files +14 −2
  1. kriss39 commented at 9:21 AM on October 23, 2026: contributor

    /rest/spenttxouts/<hash> reads the undo file for every block above genesis. For a block that was stored but never connected (a side branch) or whose undo data was pruned, there is no undo position, so OpenUndoFile() fails and ReadBlockUndo() writes OpenUndoFile failed for FlatFilePos(nFile=-1, nPos=0) to debug.log with LogError. The request itself already returns 404, but each unauthenticated request for such a block adds an [error] line that looks like disk corruption.

    This checks CheckBlockDataAvailability() for BLOCK_HAVE_UNDO before reading, so nothing is logged. Pruning clears BLOCK_HAVE_UNDO, so pruned blocks are covered too. The response is unchanged.

    The new check at the end of interface_rest.py requests a stale block and fails on master because of the logged error.

  2. DrahtBot added the label RPC/REST/ZMQ on Oct 23, 2026
  3. DrahtBot commented at 9:21 AM on October 23, 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.

    Type Reviewers
    ACK maflcko, stickies-v

    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.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. in src/rest.cpp:377 in be3c1db50f
     371 | @@ -372,8 +372,12 @@ static bool rest_spent_txouts(const std::any& context, HTTPRequest* req, const s
     372 |      }
     373 |  
     374 |      CBlockUndo block_undo;
     375 | -    if (pblockindex->nHeight > 0 && !chainman->m_blockman.ReadBlockUndo(block_undo, *pblockindex)) {
     376 | -        return RESTERR(req, HTTP_NOT_FOUND, hashStr + " undo not available");
     377 | +    if (pblockindex->nHeight > 0) {
     378 | +        // Blocks that were never connected or have been pruned have no undo data.
     379 | +        const bool have_undo{WITH_LOCK(cs_main, return (pblockindex->nStatus & BLOCK_HAVE_UNDO) && !chainman->m_blockman.IsBlockPruned(*pblockindex))};
    


    stickies-v commented at 10:13 AM on October 23, 2026:

    I think the && !chainman->m_blockman.IsBlockPruned(*pblockindex) check here is redundant?


    maflcko commented at 10:39 AM on October 23, 2026:

    Can this use CheckBlockDataAvailability to avoid duplicating the impl?


    kriss39 commented at 10:59 AM on October 23, 2026:

    Thanks, both right. PruneOneBlockFile() clears BLOCK_HAVE_UNDO, so the IsBlockPruned() check added nothing. It now uses CheckBlockDataAvailability(*pblockindex, *pblockindex, BlockStatus{BLOCK_HAVE_UNDO}), in e8af2c7488925e35ffeaf64e523cef48b70280eb.


    stickies-v commented at 11:33 AM on October 23, 2026:

    I think a simple pblockindex->nStatus & BLOCK_HAVE_UNDO is more straightforward tbh but either way works.


    maflcko commented at 2:56 PM on October 23, 2026:

    yeah, i was thinking that the rpc CheckBlockDataAvailability would provide better error messages, but if they are not used, a plain nStatus & BLOCK_HAVE_UNDO seems fine.

  5. stickies-v commented at 10:17 AM on October 23, 2026: contributor

    Approach ACK

  6. rest: don't log an error for /spenttxouts on a block without undo data
    `/rest/spenttxouts/<hash>` calls `ReadBlockUndo()` for every block above
    genesis. For a block that was stored but never connected (a side branch)
    or whose undo data was pruned, `GetUndoPos()` is null, so
    `OpenUndoFile()` fails and `ReadBlockUndo()` writes "OpenUndoFile failed
    for FlatFilePos(nFile=-1, nPos=0)" to debug.log with `LogError`. The
    endpoint then correctly answers 404, but every unauthenticated request
    for such a block adds an `[error]` line that looks like disk corruption.
    
    Check `CheckBlockDataAvailability()` for `BLOCK_HAVE_UNDO` first and
    only read the undo file when it can exist. Pruning clears
    `BLOCK_HAVE_UNDO`, so this covers pruned blocks too. The response is
    unchanged.
    
    The new interface_rest.py check requests a side-branch block and fails
    on master because of the logged error.
    e8af2c7488
  7. kriss39 force-pushed on Oct 23, 2026
  8. in src/rest.cpp:377 in e8af2c7488
     371 | @@ -372,8 +372,12 @@ static bool rest_spent_txouts(const std::any& context, HTTPRequest* req, const s
     372 |      }
     373 |  
     374 |      CBlockUndo block_undo;
     375 | -    if (pblockindex->nHeight > 0 && !chainman->m_blockman.ReadBlockUndo(block_undo, *pblockindex)) {
     376 | -        return RESTERR(req, HTTP_NOT_FOUND, hashStr + " undo not available");
     377 | +    if (pblockindex->nHeight > 0) {
     378 | +        // Blocks that were never connected or have been pruned have no undo data.
     379 | +        const bool have_undo{WITH_LOCK(cs_main, return chainman->m_blockman.CheckBlockDataAvailability(*pblockindex, *pblockindex, BlockStatus{BLOCK_HAVE_UNDO}))};
    


    maflcko commented at 11:13 AM on October 23, 2026:

    heh, that's funny. I was talking about src/rpc/blockchain.h:void CheckBlockDataAvailability(node::BlockManager& blockman, const CBlockIndex& blockindex, bool check_for_undo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);, but I guess this works as well.

    edit: I was thinking about CheckBlockDataAvailability from the rpc, to have more accurate error messages, but maybe that is not too important for the rest interface.

  9. maflcko approved
  10. maflcko commented at 11:13 AM on October 23, 2026: member

    lgtm ACK e8af2c7488925e35ffeaf64e523cef48b70280eb

  11. stickies-v commented at 11:33 AM on October 23, 2026: contributor

    ACK e8af2c7488925e35ffeaf64e523cef48b70280eb


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-26 18:51 UTC

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