{
 "number": 35581,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35581",
 "title": "node: add block template manager and track waitNext fee inflow",
 "author": "ismaelsadeeq",
 "author_association": "MEMBER",
 "created_at": "2026-06-22T10:50:47Z",
 "updated_at": "2026-09-16T22:41:56Z",
 "age_days": 87,
 "draft": true,
 "labels": [
  "Mining",
  "IPC"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "24a87b78695ce11fd2d47226786161edd0838621",
 "head_ref": "07-2026-block-template-man",
 "head_repo": "ismaelsadeeq/bitcoin",
 "head_history": [
  {
   "t": "2026-06-22T15:27:49Z",
   "sha": "e03f222f063caa12a460d55826015fa690a17e98"
  },
  {
   "t": "2026-06-23T10:25:53Z",
   "sha": "28c99343f3a254cc9abba62797e28f1515b9eb46"
  },
  {
   "t": "2026-06-24T09:46:02Z",
   "sha": "8c73017dabb34d21b8b4bb86ad9abdebafab434b"
  },
  {
   "t": "2026-07-07T13:43:09Z",
   "sha": "5ab4ebb9a2d15afb88d5d62f7f28239f331726d1"
  },
  {
   "t": "2026-07-08T09:29:03Z",
   "sha": "828a7e3528ae5292a7be46a8a9705857fa9d7bc6"
  },
  {
   "t": "2026-09-13T13:20:45Z",
   "sha": "d54d1ba149ac82230afec659866a5acbeaacc469"
  },
  {
   "t": "2026-09-13T19:40:23Z",
   "sha": "0abdb6005959b5639a8cc4f78159e534939bc55c"
  },
  {
   "t": "2026-09-13T20:17:05Z",
   "sha": "111870f80e05515f4b0b43fbdc89ee6b9cd9e7f7"
  },
  {
   "t": "2026-09-15T11:19:55Z",
   "sha": "24a87b78695ce11fd2d47226786161edd0838621"
  }
 ],
 "additions": 2664,
 "deletions": 587,
 "changed_files": 51,
 "commit_count": 27,
 "size_bucket": "XL",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "w0xlt",
      "url": "https://github.com/bitcoin/bitcoin/pull/35581#issuecomment-4772919793"
     },
     {
      "login": "pablomartin4btc",
      "url": "https://github.com/bitcoin/bitcoin/pull/35581#pullrequestreview-4609115523"
     }
    ]
   },
   "conflicts": [
    {
     "number": 36244,
     "title": "validation, net: Process blocks asynchronously and reduce cs_main contention",
     "author": "w0xlt"
    },
    {
     "number": 36188,
     "title": "crypto: plug hardware optimized SHA256 into libsecp256k1's context",
     "author": "furszy"
    },
    {
     "number": 36182,
     "title": "fees: return `block_policy` fee rate estimate when `mempool_policy` is not ready",
     "author": "ismaelsadeeq"
    },
    {
     "number": 36156,
     "title": "mining: include chunks that exactly fill block limits",
     "author": "l0rinc"
    },
    {
     "number": 36109,
     "title": "test: harden arbitrary-parent block creation",
     "author": "l0rinc"
    },
    {
     "number": 36097,
     "title": "mining: replace interrupt methods with cancellation arguments",
     "author": "xyzconstant"
    },
    {
     "number": 36091,
     "title": "test: Add debug output to common tested types",
     "author": "rustaceanrob"
    },
    {
     "number": 36047,
     "title": "rpc: handle createNewBlock() returning nullptr during shutdown",
     "author": "chriszeng1010"
    },
    {
     "number": 36015,
     "title": "txorphanage: bound orphan memory by storing transactions serialized",
     "author": "brunoerg"
    },
    {
     "number": 36000,
     "title": "validation: prefetch blocks while connecting",
     "author": "l0rinc"
    },
    {
     "number": 35713,
     "title": "Remove boost as a unit test runner",
     "author": "rustaceanrob"
    },
    {
     "number": 35671,
     "title": "mining: add TxCollection to bandwidth-efficiently validate external block templates",
     "author": "Sjors"
    },
    {
     "number": 35646,
     "title": "RFC: Separate out runtime errors from BlockValidationState using `util::Expected`",
     "author": "yuvicc"
    },
    {
     "number": 35569,
     "title": "Encapsulation for CTransaction",
     "author": "purpleKarrot"
    },
    {
     "number": 35511,
     "title": "RFC: consensus: Make `CAmount` a class",
     "author": "hodlinator"
    },
    {
     "number": 33922,
     "title": "mining: add getMemoryLoad() and track template non-mempool memory footprint",
     "author": "Sjors"
    },
    {
     "number": 32468,
     "title": "rpc: generateblock to allow multiple outputs",
     "author": "polespinasa"
    },
    {
     "number": 31117,
     "title": "miner: Reorg Testnet4 minimum difficulty blocks",
     "author": "fjahr"
    },
    {
     "number": 29700,
     "title": "kernel, refactor: return error status on all fatal errors",
     "author": "ryanofsky"
    }
   ]
  }
 },
 "acks_parsed": {
  "w0xlt": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-06-22T20:50:01Z",
   "stale": false
  },
  "pablomartin4btc": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-07-01T13:37:08Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "Sjors",
   "pablomartin4btc",
   "w0xlt"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-09-15T11:19:55Z",
  "last_reviewer_activity": "2026-07-01T13:37:08Z",
  "last_reviewer": "pablomartin4btc",
  "author_silent_days": 2,
  "waiting_on_author_days": 0,
  "days_since_update": 0
 },
 "refs": {
  "mentioned": [
   34803,
   35580,
   35675
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 34803,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "mempool: asynchronous mempool fee rate diagram updates via validation interface"
   },
   {
    "number": 35580,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-08-24",
    "title": "bugfix:  compare non-adjusted chunk weight against block weight limit"
   },
   {
    "number": 35675,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "mining: add block template manager"
   }
  ],
  "conflicts": [
   36244,
   36188,
   36182,
   36156,
   36109,
   36097,
   36091,
   36047,
   36015,
   36000,
   35713,
   35671,
   35646,
   35569,
   35511,
   33922,
   32468,
   31117,
   29700
  ]
 },
 "stack": {
  "shares_commits_with": [
   33922,
   35675
  ],
  "based_on": [
   35675
  ],
  "base_for": []
 },
 "review_paths": [
  "src/node/block_template_manager.cpp"
 ],
 "body": "### Motivation\n\n  The mining interface and rpc helpers (`WaitAndCreateNewBlock` and friends) are free functions scattered across `src/node/miner.cpp`, and every caller has to pass `ChainstateManager` and `KernelNotifications` into them, which is verbose. `SubmitBlock` spins up a short-lived `CValidationInterface` subscriber on every call just to read back the block validation state. This PR adds a BlockTemplateManager  that holds that state and exposes those helpers as methods, so callers don't have to  thread chainman/notifications (or a throwaway subscriber) around.\n\n It also removes a redundant pattern in `waitNext`. Currently, to decide whether mempool fee  inflow rose enough to be worth a new template, waitNext locks `cs_main` and assembles a  full block template every tick just to sum its fees and compare. After cluster mempool see https://delvingbitcoin.org/t/determining-blocktemplate-fee-increase-using-fee-rate-diagram/2052, we shouldn't have to build a whole block template to answer that question. This PR uses the #34803 mempool notifications to record the previous template state and track the inflow above the lowest  included chunk, and only assembles and returns a new template once that inflow is above the threshold.\n\n I  added a fuzz harness and unit tests for the manager. The fuzz test already caught a bug in the miner where it skips legitimate transactions due to an incorrect block chunk size limit check #35580.\n\n ### Changes\n\n  - Populate the tx refs in the fee rate diagrams\n  - Cache fee rate diagrams as chunks in ChangeSet and add SnapshotDiagrams\n  - Add a `MempoolUpdated` notification that returns the before and after diagrams\n  - Track the selected chunk information after each mempool update\n  - Add fee-inflow staleness detection per template\n  - Introduce a `BlockTemplateManager` wrapper around `BlockAssembler` that holds state and\n    creates templates, and move the free functions (mining args, SubmitBlock, GetTip,\n    WaitTipChanged, CooldownIfHeadersAhead, WaitAndCreateNewBlock) onto it as methods\n  - Use the tracked inflow in waitNext instead of rebuilding a template each tick\n  - Route in-process RPC and test template creation through `BlockTemplateManager` instead\n    of the IPC Mining interface, which also drops the per-access block copies the IPC\n    accessors (getBlock) forced\n  - Add a fuzz test and unit tests\n\n  There are now two entry points for template creation. Mining clients go through the IPC\n  Mining interface and get tracked templates, while in-process RPC and tests call  BlockTemplateManager directly and get untracked ones. This is deliberate: one-shot RPC  templates don't need staleness tracking, and it also avoids process-static RPC caches owning BlockTemplateImpl objects whose destructor reaches back into NodeContext at shutdown.\n\n50% of the code addition here are tests ~1090 lines",
 "commits": [
  {
   "sha": "482a5d27124c4241c27ed323659914cd38409650",
   "date": "2026-09-13T10:33:47Z",
   "message": "node: introduce BlockTemplateManager\n\nAdd BlockTemplateManager, a wrapper around\nBlockAssembler::CreateNewBlock(), and store it in NodeContext.\n\nWire it into node init and test setup so it is reset before its\nmempool/chainman dependencies, and update tests and fuzz setups that\nrebuild chainman or mempool. Add a unit test that verifies a block\ntemplate can be created through the manager."
  },
  {
   "sha": "bcdadf2b7111a061d2bbeba350233db7b258a787",
   "date": "2026-09-13T11:28:23Z",
   "message": "node: move mining_args to BlockTemplateManager\n\nPass the parsed mining args to BlockTemplateManager at construction\nand expose them via BlockCreateArgs(), so the manager owns the\ninit-time block create options instead of NodeContext."
  },
  {
   "sha": "07964c525d4769d00004b9942225a2cb1306e09d",
   "date": "2026-09-13T11:28:23Z",
   "message": "miner: move SubmitBlock into BlockTemplateManager\n\nMove SubmitBlockStateCatcher and SubmitBlock from miner.cpp into\nBlockTemplateManager as a member function. This groups block submission\nwith block creation in the same class. The function uses m_chainman\ndirectly instead of taking it as a parameter."
  },
  {
   "sha": "037d3519f2ff9937aa82060a42939aafab4179f1",
   "date": "2026-09-13T11:28:25Z",
   "message": "node: move tip and wait helpers into BlockTemplateManager\n\nMove the mining tip lookup and block-template waiting helpers (GetTip,\nWaitTipChanged, WaitAndCreateNewBlock, InterruptWait,\nCooldownIfHeadersAhead) into BlockTemplateManager so the manager owns\nthe template waiting flow. The manager now takes KernelNotifications\nat construction."
  },
  {
   "sha": "400ac328c91b653e793bd140b89e8fabfb42e3ac",
   "date": "2026-09-13T11:28:26Z",
   "message": "interfaces: create block template via BlockTemplateManager\n\nRoute the Mining interface's createNewBlock() through\nBlockTemplateManager::CreateNewTemplate() instead of constructing a\nBlockAssembler directly. Merging the init-time defaults into unset\noptions now happens inside CreateNewTemplate(), so every caller gets\nthem applied."
  },
  {
   "sha": "011cbfbcd2e3a3282ae7e5afdfd923bc444d1845",
   "date": "2026-09-13T11:28:27Z",
   "message": "rpc: route getblocktemplate internals through node\n\nAdd EnsureBlockTemplateManager() and use it in getblocktemplate for tip\nlookup and longpoll waiting, while using ChainstateManager directly for\ntest-chain and IBD checks."
  },
  {
   "sha": "0998c0bbdfcc3c3f7c105a1fb7223bace529556a",
   "date": "2026-09-13T11:28:28Z",
   "message": "rpc: build getblocktemplate via BlockTemplateManager"
  },
  {
   "sha": "951fac807d37302e7de5e289c0ab05f8dfcb1e1c",
   "date": "2026-09-13T11:28:29Z",
   "message": "rpc: do not copy template data in getblocktemplate\n\nThe transactions, fees and sigops costs, and the coinbase outputs\nare only read, so reference them from the template instead of copying\nthem out of it."
  },
  {
   "sha": "38556f817e060187b48cd31490f578cdf63134ee",
   "date": "2026-09-13T11:28:29Z",
   "message": "rpc: only copy the header in getblocktemplate\n\nThe block copy exists solely to apply header adjustments (time, nonce,\nversion bits) that must not mutate the cached template. Now that the\ntransactions are read directly from the template, copy only the header\ninstead of the entire block."
  },
  {
   "sha": "8372721f20e2ea2c15bae38a046476736169d801",
   "date": "2026-09-13T11:28:30Z",
   "message": "rpc: build generation templates via BlockTemplateManager\n\ngenerateblock is no longer safe for fuzzing: it previously threw at\nEnsureMining (node.mining is never set in the fuzz setup), but with\nEnsureBlockTemplateManager it now executes, mining and submitting a\nreal block. Submission mutates the chain state shared across fuzz\niterations and writes the block to disk."
  },
  {
   "sha": "ec4f24ef181a7987bcea72a21e507f59dc1b8126",
   "date": "2026-09-13T11:28:31Z",
   "message": "rpc: wait for tips via BlockTemplateManager\n\nThe waitforblock, waitforblockheight and waitfornewblock RPCs are no\nlonger safe for fuzzing: they previously threw at EnsureMining\n(node.mining is never set in the fuzz setup), but with\nEnsureBlockTemplateManager they now really wait. The tip never changes\nduring fuzzing and nothing interrupts the wait, so a call without a\ntimeout blocks forever."
  },
  {
   "sha": "6c71166bcfa4339d5019f2b27d477eb45ce7fe86",
   "date": "2026-09-13T11:28:32Z",
   "message": "test: create templates via BlockTemplateManager"
  },
  {
   "sha": "ffe3a631f38b1224db8b0ea246a3c976f358c59e",
   "date": "2026-09-13T11:28:33Z",
   "message": "node: remove NodeContext::mining and EnsureMining"
  },
  {
   "sha": "3d7d190b6995b3c0adb6528c2d9eac81a8f839d9",
   "date": "2026-09-13T11:28:34Z",
   "message": "ci: enforce iwyu for block template manager"
  },
  {
   "sha": "e8b283c35a656f808250e4b32d3494f49a000b08",
   "date": "2026-09-13T11:28:35Z",
   "message": "test: fuzz BlockTemplateManager"
  },
  {
   "sha": "bfe71afd434083a67f70ee8a1964f8296298262b",
   "date": "2026-09-13T13:11:51Z",
   "message": "txgraph: populate chunk refs in `GetMainStagingDiagrams` result\n\nGetMainStagingDiagrams currently returns a pair of vector<FeeFrac>\ncontaining only chunk feerates. Some callers need to know which\ntransactions belong to each chunk in order to compute a chunk hash.\n\nIntroduce TxGraph::Chunk, which pairs a chunk feerate with the refs of\nall transactions in that chunk. Update GetMainStagingDiagrams to return a\npair of vector<TxGraph::Chunk>, and rename AppendChunkFeerates to\nAppendChunks to reflect the richer return type.\n\nAdd SanityCheck coverage for the new behaviour."
  },
  {
   "sha": "cc79146ba9b5580feb443a7d93deffa69a4651fe",
   "date": "2026-09-13T13:11:53Z",
   "message": "refactor: move-only: split GetPackageHash"
  },
  {
   "sha": "b8c8feebcbe6e5aea16b11ed18694f68a7414591",
   "date": "2026-09-13T13:11:54Z",
   "message": "mempool: cache fee rate diagrams as chunks in ChangeSet\n\nCalculateChunksForRBF extracts only the FeeFrac from each TxGraph::Chunk\nand discards the rest. Cache the fee rate diagram chunks in ChangeSet for\nuse in subsequent commits."
  },
  {
   "sha": "e2dc04ed1651e9ca1d8be64578460a1bc4c79b60",
   "date": "2026-09-13T13:11:55Z",
   "message": "mempool: add SnapshotDiagrams to ChangeSet\n\nExtract SnapshotDiagrams from CalculateChunksForRBF so the diagram\nsnapshot can be taken on removal paths that do not go through the RBF\ncodepath.\n\nThe const fix to RemoveStaged is required because GetRemovals()\nreturns a const reference."
  },
  {
   "sha": "d7c2a0fa4e7d7376f8757e8330411de102d2efc7",
   "date": "2026-09-13T13:11:55Z",
   "message": "refactor: move-only: extract dependency addition into a separate method"
  },
  {
   "sha": "4428f963e009909ea197aa3e21574b76b69eed45",
   "date": "2026-09-15T09:59:45Z",
   "message": "mempool: add and fire MempoolUpdated signal on each mempool update path\n\nAdd MemPoolChunk and MemPoolChunksUpdate structs to\nkernel/mempool_entry.h and MakeMemPoolChunks helper to txmempool.cpp\nfor converting TxGraph::Chunk vectors into MemPoolChunk vectors.\n\nEach removal path now captures the before/after fee rate diagram chunks\nand fires MempoolUpdated so subscribers can observe every mempool change.\n\nThis signal allows subscribers to observe mempool fee rate diagram\nchanges in an asynchronous way without holding the mempool lock.\n\nThis changes the order of operations in removeForBlock: all block\ntransactions in the mempool are now removed before conflict\nremovals.\n\nIn blockencodings_tests, SyncWithValidationInterfaceQueue() drains the\nasync MempoolUpdated signal queue before LOCK2(cs_main, pool.cs).\nThe LOCK2 moves after the sync to avoid deadlock."
  },
  {
   "sha": "aa4d25509ae297335046cb37dbae31cda8a62d4e",
   "date": "2026-09-15T09:59:45Z",
   "message": "test: add unit test for mempool update validation events"
  },
  {
   "sha": "d05e6996f9a8b2093f1bb25cfc0a5df719a2668b",
   "date": "2026-09-15T09:59:45Z",
   "message": "miner: track selected chunks in block templates\n\nReplace `m_package_feerates` with `m_template_chunks`, which records\neach selected chunk's `FeePerWeight` feerate, unadjusted weight, sigops\ncost, and the witness IDs of the transactions selected in that chunk.\n\nThis gives block templates enough information to describe both the\nselection order and the transaction group selected at each step."
  },
  {
   "sha": "038feb87598ebd6329601cd72717a3f21cf8f79d",
   "date": "2026-09-15T09:59:45Z",
   "message": "node: add block template snapshot tracking\n\nIndex template chunks by hash and feerate to update\nsnapshots without sorting them after each mempool addition."
  },
  {
   "sha": "ae40e1770d15366cdb64112406e5776ae5a00d15",
   "date": "2026-09-15T09:59:45Z",
   "message": "node: update template snapshots from mempool callbacks\n\nRegister BlockTemplateManager for validation callbacks\nand keep tracked snapshots synchronized with mempool and\nchain-tip changes."
  },
  {
   "sha": "93c7112104f1b48850ed03ecd19607423aa34a71",
   "date": "2026-09-15T09:59:45Z",
   "message": "node: add block template staleness detection\n\nTrack template fee inflow and report staleness once the fee improvement\nreaches the requested threshold. The fee improvement is the lower-bound\ndifference between the current tracked chunk fees and the original\ntemplate fees."
  },
  {
   "sha": "24a87b78695ce11fd2d47226786161edd0838621",
   "date": "2026-09-15T09:59:45Z",
   "message": "miner: use tracked fee inflow for waitNext\n\nUse BlockTemplateManager snapshot tracking to\ndecide when waitNext should return a replacement\ntemplate due to fee inflow.\n\nThis avoids rebuilding full templates on every wait\ntick just to compare fees. Tracked snapshots are cleaned\nup by BlockTemplateImpl destruction, so an original template\ncan remain alive and call waitNext again after a replacement is returned."
  }
 ],
 "timeline": [
  {
   "t": "2026-06-22T15:27:49Z",
   "kind": "force_push",
   "who": "ismaelsadeeq",
   "commit": "e03f222f063caa12a460d55826015fa690a17e98"
  },
  {
   "t": "2026-06-22T20:50:01Z",
   "kind": "comment",
   "who": "w0xlt",
   "assoc": "CONTRIBUTOR",
   "text": "Concept ACK"
  },
  {
   "t": "2026-06-23T10:25:53Z",
   "kind": "force_push",
   "who": "ismaelsadeeq",
   "commit": "28c99343f3a254cc9abba62797e28f1515b9eb46"
  },
  {
   "t": "2026-06-24T09:46:02Z",
   "kind": "force_push",
   "who": "ismaelsadeeq",
   "commit": "8c73017dabb34d21b8b4bb86ad9abdebafab434b"
  },
  {
   "t": "2026-06-25T14:59:12Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "It would be nice to have a PR focussed on the BlockTemplateManager:\n\n- 08181220b6 `node: introduce block template manager`\n- 8a4363ce6e `test: add block template manager fuzz test`\n- 595acb3762 `interfaces: create block template via block template manager`\n- cbc15a02e2 `node: move mining_args to block template manager`\n- f7f496d8dc `miner: move SubmitBlock into BlockTemplateManager`\n- 9099f6d875 `node: move tip and wait helpers into BlockTemplateManager`\n- dcbd4dbeb6 `rpc, test: build block templates via BlockTemplateManager`\n\nI should be able to build https://github.com/bitcoin/bitcoin/pull/33922 / https://github.com/Sjors/bitcoin/pull/120 on top of that.\n\nThe `waitNext()` cluster mempool enhancement would be a natural followup."
  },
  {
   "t": "2026-07-01T12:52:02Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/node/block_template_manager.cpp",
   "commit": "8c73017dabb34d21b8b4bb86ad9abdebafab434b",
   "in_reply_to": null,
   "text": "IsStale is a public method but has an implicit precondition: options must match the ones used when `template_id` was created, otherwise it silently returns false. Could a comment document this (if appropriate)?"
  },
  {
   "t": "2026-07-01T13:11:28Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/node/block_template_manager.cpp",
   "commit": "24a87b78695ce11fd2d47226786161edd0838621",
   "in_reply_to": null,
   "text": "There was a comment there in the old code that was removed as I think part of it was no longer accurate. Perhaps it can be add:\n```\n// Alternate waiting for a new tip and checking if fees have risen.\n// The staleness check is cheap but template creation is not, so we only rebuild once per second.\n```"
  },
  {
   "t": "2026-07-01T13:37:08Z",
   "kind": "review",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "8c73017dabb34d21b8b4bb86ad9abdebafab434b",
   "text": "Concept ACK -  first time reviewing this area.\n\nI can see this PR is based on top of #34803 (first 7 commits). The approach of moving free functions onto a class that holds state plus incremental snapshot tracking to avoid full template rebuilds seems clean. The fuzz test catching an actual bug (#35580) is a strong signal.\n\nLeft a few comments."
  },
  {
   "t": "2026-07-01T15:46:26Z",
   "kind": "comment",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "text": "Thanks for taking a look at this @pablomartin4btc, I will address these comments when I open up a PR that adds the block template manager alone, as @Sjors suggested https://github.com/bitcoin/bitcoin/pull/35581#issuecomment-4800772480."
  },
  {
   "t": "2026-07-07T11:07:23Z",
   "kind": "review_comment",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "path": "src/node/block_template_manager.cpp",
   "commit": "24a87b78695ce11fd2d47226786161edd0838621",
   "in_reply_to": 3506167320,
   "text": "Fixed in #35675"
  },
  {
   "t": "2026-07-07T13:43:09Z",
   "kind": "force_push",
   "who": "ismaelsadeeq",
   "commit": "5ab4ebb9a2d15afb88d5d62f7f28239f331726d1"
  },
  {
   "t": "2026-07-08T09:29:03Z",
   "kind": "force_push",
   "who": "ismaelsadeeq",
   "commit": "828a7e3528ae5292a7be46a8a9705857fa9d7bc6"
  },
  {
   "t": "2026-09-13T13:20:45Z",
   "kind": "force_push",
   "who": "ismaelsadeeq",
   "commit": "d54d1ba149ac82230afec659866a5acbeaacc469"
  },
  {
   "t": "2026-09-13T19:40:23Z",
   "kind": "force_push",
   "who": "ismaelsadeeq",
   "commit": "0abdb6005959b5639a8cc4f78159e534939bc55c"
  },
  {
   "t": "2026-09-13T20:17:05Z",
   "kind": "force_push",
   "who": "ismaelsadeeq",
   "commit": "111870f80e05515f4b0b43fbdc89ee6b9cd9e7f7"
  },
  {
   "t": "2026-09-15T11:19:55Z",
   "kind": "force_push",
   "who": "ismaelsadeeq",
   "commit": "24a87b78695ce11fd2d47226786161edd0838621"
  }
 ],
 "labels_log": [
  {
   "t": "2026-06-22T12:06:22Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-23T11:57:47Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-23T22:54:20Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-24T13:51:40Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-07T15:24:47Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-07T21:36:08Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-08T11:02:53Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-08T11:05:31Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-09T13:38:31Z",
   "action": "labeled",
   "label": "Mining",
   "who": "willcl-ark"
  },
  {
   "t": "2026-07-09T13:38:31Z",
   "action": "labeled",
   "label": "interfaces",
   "who": "willcl-ark"
  },
  {
   "t": "2026-07-23T00:52:46Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-13T13:36:37Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-13T15:05:14Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-15T13:05:06Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-07-07T11:06:48Z",
   "kind": "convert_to_draft",
   "who": "ismaelsadeeq"
  }
 ],
 "text_chars": 11656,
 "text_tokens_estimate": 2914,
 "changed_paths": [
  "ci/test/03_test_script.sh",
  "src/CMakeLists.txt",
  "src/bench/mempool_stress.cpp",
  "src/init.cpp",
  "src/kernel/mempool_entry.h",
  "src/node/block_template_manager.cpp",
  "src/node/block_template_manager.h",
  "src/node/context.cpp",
  "src/node/context.h",
  "src/node/interfaces.cpp",
  "src/node/miner.cpp",
  "src/node/miner.h",
  "src/node/mining_types.h",
  "src/policy/fees/mempool_estimator.cpp",
  "src/policy/packages.cpp",
  "src/rpc/blockchain.cpp",
  "src/rpc/mining.cpp",
  "src/rpc/server_util.cpp",
  "src/rpc/server_util.h",
  "src/test/CMakeLists.txt",
  "src/test/blockencodings_tests.cpp",
  "src/test/fuzz/CMakeLists.txt",
  "src/test/fuzz/block_template_manager.cpp",
  "src/test/fuzz/connect_block.cpp",
  "src/test/fuzz/package_eval.cpp",
  "src/test/fuzz/rpc.cpp",
  "src/test/fuzz/tx_pool.cpp",
  "src/test/fuzz/txgraph.cpp",
  "src/test/fuzz/utxo_snapshot.cpp",
  "src/test/mempool_tests.cpp",
  "src/test/mempool_update_tests.cpp",
  "src/test/miner_tests.cpp",
  "src/test/peerman_tests.cpp",
  "src/test/rbf_tests.cpp",
  "src/test/util/mining.cpp",
  "src/test/util/setup_common.cpp",
  "src/test/util/setup_common.h",
  "src/test/util/validation.cpp",
  "src/test/validation_block_tests.cpp",
  "src/test/validation_chainstatemanager_tests.cpp",
  "src/txgraph.cpp",
  "src/txgraph.h",
  "src/txmempool.cpp",
  "src/txmempool.h",
  "src/util/hasher.cpp",
  "src/util/hasher.h",
  "src/validation.cpp",
  "src/validationinterface.cpp",
  "src/validationinterface.h",
  "src/wallet/test/fuzz/fees.cpp",
  "test/functional/interface_zmq.py"
 ],
 "files": [
  {
   "path": "ci/test/03_test_script.sh",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/bench/mempool_stress.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/init.cpp",
   "add": 15,
   "del": 8
  },
  {
   "path": "src/kernel/mempool_entry.h",
   "add": 18,
   "del": 0
  },
  {
   "path": "src/node/block_template_manager.cpp",
   "add": 487,
   "del": 0
  },
  {
   "path": "src/node/block_template_manager.h",
   "add": 235,
   "del": 0
  },
  {
   "path": "src/node/context.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/node/context.h",
   "add": 3,
   "del": 11
  },
  {
   "path": "src/node/interfaces.cpp",
   "add": 35,
   "del": 27
  },
  {
   "path": "src/node/miner.cpp",
   "add": 8,
   "del": 244
  },
  {
   "path": "src/node/miner.h",
   "add": 15,
   "del": 61
  },
  {
   "path": "src/node/mining_types.h",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/policy/fees/mempool_estimator.cpp",
   "add": 8,
   "del": 2
  },
  {
   "path": "src/policy/packages.cpp",
   "add": 4,
   "del": 14
  },
  {
   "path": "src/rpc/blockchain.cpp",
   "add": 15,
   "del": 16
  },
  {
   "path": "src/rpc/mining.cpp",
   "add": 36,
   "del": 38
  },
  {
   "path": "src/rpc/server_util.cpp",
   "add": 4,
   "del": 4
  },
  {
   "path": "src/rpc/server_util.h",
   "add": 2,
   "del": 4
  },
  {
   "path": "src/test/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/test/blockencodings_tests.cpp",
   "add": 9,
   "del": 4
  },
  {
   "path": "src/test/fuzz/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/test/fuzz/block_template_manager.cpp",
   "add": 556,
   "del": 0
  },
  {
   "path": "src/test/fuzz/connect_block.cpp",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/test/fuzz/package_eval.cpp",
   "add": 0,
   "del": 1
  },
  {
   "path": "src/test/fuzz/rpc.cpp",
   "add": 4,
   "del": 4
  },
  {
   "path": "src/test/fuzz/tx_pool.cpp",
   "add": 1,
   "del": 2
  },
  {
   "path": "src/test/fuzz/txgraph.cpp",
   "add": 23,
   "del": 12
  },
  {
   "path": "src/test/fuzz/utxo_snapshot.cpp",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/test/mempool_tests.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/test/mempool_update_tests.cpp",
   "add": 535,
   "del": 0
  },
  {
   "path": "src/test/miner_tests.cpp",
   "add": 278,
   "del": 34
  },
  {
   "path": "src/test/peerman_tests.cpp",
   "add": 5,
   "del": 4
  },
  {
   "path": "src/test/rbf_tests.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/test/util/mining.cpp",
   "add": 9,
   "del": 8
  },
  {
   "path": "src/test/util/setup_common.cpp",
   "add": 34,
   "del": 8
  },
  {
   "path": "src/test/util/setup_common.h",
   "add": 6,
   "del": 0
  },
  {
   "path": "src/test/util/validation.cpp",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/test/validation_block_tests.cpp",
   "add": 10,
   "del": 9
  },
  {
   "path": "src/test/validation_chainstatemanager_tests.cpp",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/txgraph.cpp",
   "add": 47,
   "del": 17
  },
  {
   "path": "src/txgraph.h",
   "add": 21,
   "del": 4
  },
  {
   "path": "src/txmempool.cpp",
   "add": 149,
   "del": 41
  },
  {
   "path": "src/txmempool.h",
   "add": 9,
   "del": 2
  },
  {
   "path": "src/util/hasher.cpp",
   "add": 19,
   "del": 0
  },
  {
   "path": "src/util/hasher.h",
   "add": 4,
   "del": 0
  },
  {
   "path": "src/validation.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/validationinterface.cpp",
   "add": 24,
   "del": 0
  },
  {
   "path": "src/validationinterface.h",
   "add": 9,
   "del": 0
  },
  {
   "path": "src/wallet/test/fuzz/fees.cpp",
   "add": 3,
   "del": 0
  },
  {
   "path": "test/functional/interface_zmq.py",
   "add": 2,
   "del": 2
  }
 ],
 "test_lines": 1585,
 "git": {
  "head": "24a87b78695ce11fd2d47226786161edd0838621",
  "head_matches_backup": true,
  "base": "17817818da3cb67c95320b7a5d4d69bd649c1fbf",
  "commits": [
   {
    "sha": "482a5d2712",
    "subject": "node: introduce BlockTemplateManager",
    "files": 13,
    "add": 110,
    "del": 0
   },
   {
    "sha": "bcdadf2b71",
    "subject": "node: move mining_args to BlockTemplateManager",
    "files": 8,
    "add": 28,
    "del": 23
   },
   {
    "sha": "07964c525d",
    "subject": "miner: move SubmitBlock into BlockTemplateManager",
    "files": 5,
    "add": 79,
    "del": 70
   },
   {
    "sha": "037d3519f2",
    "subject": "node: move tip and wait helpers into BlockTemplateManager",
    "files": 7,
    "add": 250,
    "del": 253
   },
   {
    "sha": "400ac328c9",
    "subject": "interfaces: create block template via BlockTemplateManager",
    "files": 3,
    "add": 8,
    "del": 13
   },
   {
    "sha": "011cbfbcd2",
    "subject": "rpc: route getblocktemplate internals through node",
    "files": 5,
    "add": 28,
    "del": 6
   },
   {
    "sha": "0998c0bbdf",
    "subject": "rpc: build getblocktemplate via BlockTemplateManager",
    "files": 1,
    "add": 6,
    "del": 7
   },
   {
    "sha": "951fac807d",
    "subject": "rpc: do not copy template data in getblocktemplate",
    "files": 1,
    "add": 5,
    "del": 5
   },
   {
    "sha": "38556f817e",
    "subject": "rpc: only copy the header in getblocktemplate",
    "files": 1,
    "add": 11,
    "del": 11
   },
   {
    "sha": "8372721f20",
    "subject": "rpc: build generation templates via BlockTemplateManager",
    "files": 2,
    "add": 11,
    "del": 14
   },
   {
    "sha": "ec4f24ef18",
    "subject": "rpc: wait for tips via BlockTemplateManager",
    "files": 2,
    "add": 18,
    "del": 19
   },
   {
    "sha": "6c71166bcf",
    "subject": "test: create templates via BlockTemplateManager",
    "files": 6,
    "add": 32,
    "del": 32
   },
   {
    "sha": "ffe3a631f3",
    "subject": "node: remove NodeContext::mining and EnsureMining",
    "files": 5,
    "add": 0,
    "del": 21
   },
   {
    "sha": "3d7d190b69",
    "subject": "ci: enforce iwyu for block template manager",
    "files": 1,
    "add": 1,
    "del": 1
   },
   {
    "sha": "e8b283c35a",
    "subject": "test: fuzz BlockTemplateManager",
    "files": 2,
    "add": 330,
    "del": 0
   },
   {
    "sha": "bfe71afd43",
    "subject": "txgraph: populate chunk refs in `GetMainStagingDiagrams` result",
    "files": 4,
    "add": 102,
    "del": 34
   },
   {
    "sha": "cc79146ba9",
    "subject": "refactor: move-only: split GetPackageHash",
    "files": 3,
    "add": 27,
    "del": 14
   },
   {
    "sha": "b8c8feebcb",
    "subject": "mempool: cache fee rate diagrams as chunks in ChangeSet",
    "files": 2,
    "add": 13,
    "del": 6
   },
   {
    "sha": "e2dc04ed16",
    "subject": "mempool: add SnapshotDiagrams to ChangeSet",
    "files": 2,
    "add": 10,
    "del": 3
   },
   {
    "sha": "d7c2a0fa4e",
    "subject": "refactor: move-only: extract dependency addition into a separate method",
    "files": 2,
    "add": 10,
    "del": 1
   },
   {
    "sha": "4428f963e0",
    "subject": "mempool: add and fire MempoolUpdated signal on each mempool update path",
    "files": 12,
    "add": 187,
    "del": 49
   },
   {
    "sha": "aa4d25509a",
    "subject": "test: add unit test for mempool update validation events",
    "files": 2,
    "add": 536,
    "del": 0
   },
   {
    "sha": "d05e6996f9",
    "subject": "miner: track selected chunks in block templates",
    "files": 4,
    "add": 44,
    "del": 21
   },
   {
    "sha": "038feb8759",
    "subject": "node: add block template snapshot tracking",
    "files": 3,
    "add": 182,
    "del": 0
   },
   {
    "sha": "ae40e1770d",
    "subject": "node: update template snapshots from mempool callbacks",
    "files": 12,
    "add": 272,
    "del": 31
   },
   {
    "sha": "93c7112104",
    "subject": "node: add block template staleness detection",
    "files": 8,
    "add": 419,
    "del": 10
   },
   {
    "sha": "24a87b7869",
    "subject": "miner: use tracked fee inflow for waitNext",
    "files": 5,
    "add": 56,
    "del": 54
   }
  ],
  "patch_truncated": true
 },
 "input_hash": "39f636ae2abd6d3d",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}