mining: move getblocktemplate cache into BlockTemplateManager #36356

pull w0xlt wants to merge 2 commits into bitcoin:master from w0xlt:block-template-manager-gbt-cache changing 4 files +130 −32
  1. w0xlt commented at 8:24 AM on September 27, 2026: contributor

    Follow-up to #35675. This addresses the getblocktemplate part of the "Remove remaining global states" TODO in #33758, as suggested in #35675#pullrequestreview-5299625960.

    getblocktemplate reuses the last template it built until the tip changes, or until the mempool changed and the template is more than 5 seconds old. That cache currently lives in four function-local statics (pindexPrev, block_template, nTransactionsUpdatedLast, time_start). Because they are statics, they:

    • live as long as the process, so the cached CBlockIndex* can outlive the ChainstateManager that owns it when a process creates more than one node context (as the unit tests do);
    • rely on callers holding cs_main, which nothing checks at compile time;
    • cannot be unit tested.

    This PR moves the cache into BlockTemplateManager, which already builds templates for the RPC and the mining interface:

    • node: adds RefreshCachedTemplate() and GetCachedTransactionsUpdated(). The cache is GUARDED_BY(::cs_main), as suggested in the review linked above, so clang's thread-safety analysis checks every access. The manager reads the active tip itself and compares it with the template's hashPrevBlock, so the cache stores no CBlockIndex* and can never pair a template with the wrong tip. A new unit test covers each rebuild rule and the retry after a failed build.
    • rpc: replaces the statics with the manager's cache. pindexPrev and the longpollid now come from the template's hashPrevBlock.

    This is a move, not a redesign: no RPC behavior change is intended. The rebuild rules, the longpoll counter and the retry after a failed build work as on master. Only getblocktemplate uses the cache; it is not shared with mining interface clients.

    For now, the cache uses cs_main rather than its own mutex: the RPC already holds cs_main across the refresh, and CreateNewBlock() takes it anyway. Until the cache has readers that don't hold cs_main, a separate lock would only add a lock order without taking cs_main off the build path.

    In short: the getblocktemplate cache stops being hidden process-wide state and becomes node-owned state with checked locking and unit tests, which also gives other improvements a single place to make their changes.

  2. node: cache a getblocktemplate template in BlockTemplateManager
    Add a CachedBlockTemplate member to BlockTemplateManager, guarded by
    cs_main, along with GetCachedTransactionsUpdated() and
    RefreshCachedTemplate().
    
    RefreshCachedTemplate() follows the rules of the function-local statics
    in the getblocktemplate RPC, which the next commit replaces: the template
    is rebuilt when the tip changes, or when the mempool changed and the
    cached template is more than 5 seconds old. A failed rebuild leaves the
    cached template unset so that the next call tries again. The deprecated
    GetTime() is replaced with the equivalent Now<NodeSeconds>().
    
    Unlike the RPC, RefreshCachedTemplate() does not take the tip from the
    caller or cache its CBlockIndex. It reads the active chain tip itself
    and compares it with the template's hashPrevBlock, so the cache cannot
    pair a template with a tip it does not build on.
    ccb8e84039
  3. rpc: use the BlockTemplateManager cache in getblocktemplate
    Replace the function-local statics in getblocktemplate with the template
    cached by BlockTemplateManager. The state now lives as long as the node
    context instead of the process, and its synchronization is checked
    through GUARDED_BY(::cs_main).
    
    The static CBlockIndex pointer is not carried over: pindexPrev is looked
    up from the template's hashPrevBlock, so it can no longer outlive the
    ChainstateManager that owns it. The longpollid is built from
    hashPrevBlock as well, so it always names the block the template builds
    on, and the tip no longer needs to be re-read after longpolling.
    5cbfbc6b92
  4. DrahtBot added the label Mining on Sep 27, 2026
  5. DrahtBot commented at 8:25 AM on September 27, 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/36356.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

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

    <!--5faf32d7da4f0f540f40219e4f7537a3-->


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-27 21:51 UTC

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