{
 "number": 36356,
 "input_hash": "4218becfb5698fca",
 "model": "ledger",
 "prompt_hash": null,
 "created": "2026-10-30T01:12:40+00:00",
 "result": {
  "summary": "Moves the `getblocktemplate` block template cache from function-local static variables in the RPC handler into `BlockTemplateManager`. The cache's lifetime is bound to the node context rather than the process, raw `CBlockIndex*` pointers are replaced with hash lookups, synchronization under `cs_main` is formally annotated, and unit tests are added for template invalidation.",
  "problem": "Template caching in `getblocktemplate` previously used process-scoped static variables. This allowed cached `CBlockIndex*` pointers to outlive their owning `ChainstateManager` during unit tests, bypassed compile-time thread-safety checking for `cs_main`, and prevented unit testing of the caching and refresh logic.",
  "card": "Moves the getblocktemplate RPC cache from function-local statics into BlockTemplateManager. This eliminates process-wide global state where dangling CBlockIndex pointers could outlive ChainstateManager in tests, adds Clang thread-safety annotations under cs_main, and adds unit test coverage for template caching and invalidation rules. The refactor advances the BlockTemplateManager tracking issue #33758.",
  "evidence": [
   "Addresses the 'Remove remaining global states' TODO in tracking issue #33758.",
   "PR description points out that 'cached CBlockIndex* can outlive its ChainstateManager (as in unit tests)' and 'can't be unit tested.'"
  ],
  "scope_notes": "The change is primarily a code movement from `rpc/mining.cpp` to `node/block_template_manager.cpp`, accompanied by unit tests in `test/miner_tests.cpp`.",
  "changed_since_previous": "No structural changes to the commits or implementation; references to follow-up PR #36357 were removed.",
  "thread": {
   "last_event_at": "2026-10-28T23:10:09Z",
   "events": 11,
   "head_sha": "ed3dd1469f9a0cb43cb1dea92e32a780bceed63f",
   "schema_floor": 2,
   "schema": 2
  },
  "waiting_on": [
   {
    "at": "2026-10-28",
    "id": "c:6482952144",
    "on": "reviewer",
    "url": "https://github.com/bitcoin/bitcoin/pull/36356#issuecomment-6482952144",
    "what": "ismaelsadeeq and Sjors to review the author's replies and 3-commit split"
   }
  ],
  "risk": {
   "level": "medium",
   "touches": [
    "rpc_api",
    "other"
   ],
   "why": "A flaw in the template cache invalidation logic could serve stale templates after a tip change, leading miners to mine on an outdated tip."
  },
  "discussion": {
   "author_status": "last statement processed 2026-10-28",
   "open_concerns": [],
   "resolved_concerns": [
    "ismaelsadeeq: Implement a broader cache shared with IPC createnewblock, waitnext, and the mempool fee estimator as attempted in #33421 (accepted by ismaelsadeeq 2026-10-09)",
    "ismaelsadeeq: Should the cache be cleared on a block connection instead of keeping it until shutdown? (answered by w0xlt 2026-10-28)",
    "ismaelsadeeq: Pass max_age as a parameter so that the caching logic is not tied to getblocktemplate (answered by w0xlt 2026-10-28)"
   ]
  },
  "reviewability": {
   "state": "Ready",
   "label": "Ready",
   "reason": "Nothing known that would invalidate a review now."
  },
  "agreement": {
   "state": "Strong",
   "summary": "Strong: substantive support, no open objection (ismaelsadeeq, Sjors)",
   "reason": "Author replied to both of ismaelsadeeq's inline questions/suggestions and restructured the commits into a 3-commit split in response to Sjors's feedback.",
   "evidence": [
    "ismaelsadeeq: Concept ACK \u2014 moving template caching into BlockTemplateManager creates an opportunity to share template caching across RPC, IPC mining, and fee estimation",
    "Sjors: support \u2014 prefers to keep this simple and focussed"
   ],
   "objections": [
    {
     "reviewer": "ismaelsadeeq",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "scope",
     "harm": "",
     "request": "Implement a broader cache shared with IPC createnewblock, waitnext, and the mempool fee estimator as attempted in #33421",
     "question": "",
     "text": "Implement a broader cache shared with IPC createnewblock, waitnext, and the mempool fee estimator as attempted in #33421",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "accepted deferring to follow-ups",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "c:6065621630"
     ],
     "evidence": "2026-10-08: 'I think we can implement the broader cache as attempted here #33421, mempool estimator dependency on `ChainStateManager` will be gone, and the ipc `createnewblock`, `waitnext` and `getblocktemplate` R'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36356#issuecomment-6058035761",
     "id": "c:6058035761",
     "at": "2026-10-08",
     "status_at": "2026-10-09",
     "status_by": "ismaelsadeeq",
     "resolution_evidence": "2026-10-09: ismaelsadeeq: 'However, I agree this is a start; we can extend it later.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "ismaelsadeeq",
     "association": "MEMBER",
     "type": "question",
     "kind": "approach",
     "harm": "",
     "request": "",
     "question": "Should the cache be cleared on a block connection instead of keeping it until shutdown?",
     "text": "Should the cache be cleared on a block connection instead of keeping it until shutdown?",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author explained master already keeps it until shutdown and clearing on connect requires a notification hook better left for a follow-up",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4406943630"
     ],
     "evidence": "2026-10-09: 'The cache is kept forever till shutdown. Should we clear it on a block connection?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36356#discussion_r4226656184",
     "id": "rc:4226656184",
     "at": "2026-10-09",
     "status_at": "2026-10-28",
     "status_by": "w0xlt",
     "resolution_evidence": "2026-10-28: w0xlt: 'Clearing it on block connection would need a new notification hook in the manager, so I'd leave that for a follow-up.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "ismaelsadeeq",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "interface",
     "harm": "",
     "request": "Pass max_age as a parameter so that the caching logic is not tied to getblocktemplate",
     "question": "",
     "text": "Pass max_age as a parameter so that the caching logic is not tied to getblocktemplate",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author explained max_age fits better in a follow-up that makes the cache generic, and named the constant GBT_TEMPLATE_REBUILD_INTERVAL",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4406966061"
     ],
     "evidence": "2026-10-09: 'Should we pass the `max_age` so that it is not tied to GBT?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36356#discussion_r4226664736",
     "id": "rc:4226664736",
     "at": "2026-10-09",
     "status_at": "2026-10-28",
     "status_by": "w0xlt",
     "resolution_evidence": "2026-10-28: w0xlt: 'I'd keep `max_age` out of this PR. The cache is still a single entry built with the default options, so another caller with a different `max_age` would just keep rebuilding the GBT template.'",
     "pin": null,
     "from_schema": 2
    }
   ],
   "support": [
    {
     "reviewer": "ismaelsadeeq",
     "reason": "moving template caching into BlockTemplateManager creates an opportunity to share template caching across RPC, IPC mining, and fee estimation",
     "substantive": true,
     "verdict": "Concept ACK",
     "id": "c:6058035761",
     "url": "https://github.com/bitcoin/bitcoin/pull/36356#issuecomment-6058035761",
     "at": "2026-10-08",
     "association": "MEMBER",
     "evidence": "read",
     "areas": []
    },
    {
     "reviewer": "Sjors",
     "reason": "prefers to keep this simple and focussed",
     "substantive": true,
     "verdict": "",
     "id": "c:6465912025",
     "url": "https://github.com/bitcoin/bitcoin/pull/36356#issuecomment-6465912025",
     "at": "2026-10-28",
     "association": "MEMBER",
     "evidence": "read",
     "areas": []
    }
   ],
   "participants": [
    {
     "login": "Sjors",
     "stance": "support",
     "note": "supports keeping the scope simple and focused; suggested a 3-commit split",
     "association": "MEMBER",
     "comments": 2,
     "first": "2026-10-07",
     "last": "2026-10-28"
    },
    {
     "login": "ismaelsadeeq",
     "stance": "support",
     "note": "Concept ACK; accepted deferring broader caching, asked about clearing cache on block connection and passing max_age",
     "association": "MEMBER",
     "comments": 4,
     "first": "2026-10-08",
     "last": "2026-10-09"
    }
   ],
   "derivation": "substantive support, no open objection (ismaelsadeeq, Sjors)",
   "model_state": null,
   "corrections": [],
   "notes": "Author replied to both of ismaelsadeeq's inline questions/suggestions and restructured the commits into a 3-commit split in response to Sjors's feedback."
  },
  "dependencies": {
   "depends_on": [],
   "enables": []
  },
  "categories": [
   {
    "name": "mining",
    "member": true,
    "evidence": "Carries the Mining label, touches `BlockTemplateManager` and `rpc/mining.cpp`, and refactors the `getblocktemplate` caching logic.",
    "band": "P3",
    "reason_tag": "cleanup",
    "score": 0.35,
    "factors": {
     "bug_severity": 1,
     "leverage": 1,
     "performance": 0,
     "security_stability": 1,
     "user_value": 0
    },
    "rationale": "Cleans up node lifetime and global state by moving static template caching into `BlockTemplateManager`. As noted in the description, this prevents 'cached CBlockIndex* can outlive its ChainstateManager (as in unit tests)', enables compile-time thread safety checks, and adds unit testing coverage for template invalidation."
   },
   {
    "name": "rpc",
    "member": false,
    "evidence": "Does not change RPC interfaces, argument handling, or output; only extracts internal mining template caching logic out of `rpc/mining.cpp`.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 1,
     "leverage": 1,
     "performance": 0,
     "security_stability": 1,
     "user_value": 0
    },
    "rationale": "Category covers node programmatic interfaces and RPC machinery, whereas changes to the underlying subsystem behavior exposed by an RPC belong to that subsystem."
   }
  ],
  "confidence": "high",
  "uncertainties": [],
  "needs": []
 },
 "cost_usd": 0.0,
 "source": {
  "record": "2026-10-30T01:12:40+00:00",
  "code": "2026-10-30T01:17:10+00:00",
  "judgments": 2
 }
}