Bitcoin Core Node BlockTemplateManager
main use should be handling block template creation for other components of the node.
It should use the low-level block assembler to do that. This BlockTemplateManager
should be initialized with a pointer to the mempool and a ChainstateManager
reference. It should have access to the default block creation options and be instantiated during node startup and destroyed when the node is shutting down.
This BlockTemplateManager
should be available via the node interfaces.
During instantiation of BlockTemplateManager
, it should create an instance of the BlockAssembler
and subscribe to the validation interface BlockConnected
notification.
Other components like the Mining interface (waitNext
, createNewBlock
), Peer Manager #33191, and Fee Estimation with the mempool #30157 will request a template with their respective block creation options and the number of seconds of how fresh they want the template to be.
The BlockTemplateManager
will maintain a vector of previously built block templates as caches and check if there is a template match within the interval specified by the client. If there is, it will return the template; else it will build a new one and add it to the cache.
Whenever a new block is connected, the cache is cleared.
Future Improvement
-
Detect the fee increase in the mempool and create a new template based on that information, not just using a time interval. See discussion here: https://github.com/bitcoin/bitcoin/pull/31283#discussion_r1937451223 After this, it should be possible to add a push-based technique to the
BlockTemplateManager
where you can make a subscription to get a notification when a better template is available in the mempool or when the chain tip changes. This can effectively be used inwaitNext
and make it better than the current approach, which constantly callscreateBlockTemplate
every second and checks if it is a better template. -
Low-priority, nice-to-have: prioritize clients; the mining interface should be served first before other components. (This is low-priority because of cache and template sharing between components. If a component calls BlockTemplateManager with the same config before the mining interface, the only overhead should be the shared pointer copy, which is negligible, I think. E.g., mempool-based fee estimation has the same config as the default configs for the mining interface. However, Peer Manager seems to have a diverging config; hence the priority will result in serving it faster and will have measurable improvement.)
-
Reuse Block Template with different Config as mentioned by @ajtowns
One thing that might be interesting to think about is whether a cached template can be reused despite different block creation options. I think in practice all the options can be boiled down to “maximum total weight” and “minimum effective feerate”, in which case if you had a 995 kvB template (ie 1MvB with 5kvB reserved), and had a request for a 300 kvB template, you could conceivably quickly generate the latter from the former, without needing to touch the mempool. That could probably be done particularly quickly if you kept a simplified dependency graph of the txs in the template, so that once you had to start dropping some txs, you could easily figure out which ones were missing parents and no longer sensible to consider. (Dealing with a different minimum effective feerate probably requires caching each txs’ effective feerate, and with cpfp considerations is probably difficult to do accurately unless you keep the ancestor information or the cluster mempool chunking information).
FAQ
- Is this useful? The current approach of components each creating its instance of block assembler and effectively its own caching mechanism, as shown in #31664 and #33191, results in duplicate code and does not allow for better resource usage between the components.
- Is there a POC?
Yes, I’ve attempted this and have a branch here: https://github.com/ismaelsadeeq/bitcoin/tree/09-2025-minerman which has the mining interface
createNewBlock
using theBlockTemplateManager
. #30157 will fit in nicely and reduce a large portion of mempool forecaster code, which was the caching code: https://github.com/ismaelsadeeq/bitcoin/commit/ba9b5876ae453315b57af09654d5b12b664e897a #33191 will also fit in nicely; see: https://github.com/ismaelsadeeq/bitcoin/commit/10bd8920fd259aa47d4b96037a2302d7ae6ea41f