ipc mining: pass missing context to BlockTemplate methods (incompatible schema change)
What changed, and why it matters
This is a Bitcoin Core internal-only commit that changes the inter-process communication (IPC) schema used between the main node and external mining components. It adds a missing 'context' parameter to two mining methods so they run in their own thread and don't block other calls. The commit itself explicitly warns it is an intermediate, review-only change that should not be distributed, because it makes incompatible schema changes without bumping the version number, which could cause mismatched binaries to exchange garbage data instead of clean errors. The actual security risk is low and self-contained: it is a known, temporary incompatibility during development, not a vulnerability in shipped code.
Do not build, distribute, or run binaries from this isolated commit in production or on any network. Treat it as a review-only intermediate change. Ensure the final commit in the series that bumps the mining interface version is included before any release or deployment. Reviewers should verify that the version bump in Init.makeMining is present in the subsequent commit and that functional tests cover both old and new interface behavior if backward compatibility is desired.
Security signals we found
Incompatible IPC schema change without version bump
Explicit developer warning against distributing or connecting binaries built from this commit
Risk of garbage request/response exchange between mismatched versions rather than clean errors
Intended fix for performance/lockup issues in mining IPC methods
Marked git-bisect-skip indicating unstable intermediate state
Evidence from the diff
The commit modifies src/ipc/capnp/mining.capnp to add a Proxy.Context parameter to createNewBlock() and checkBlock() in the Mining interface, and updates Python functional tests to pass the new context argument. The stated purpose is to ensure these long-running methods execute on their own thread via the IPC proxy framework, preventing them from blocking other calls. The commit message explicitly labels this as an intermediate, review-only commit with an incompatible schema change that does not update Init.makeMining version, meaning binaries built from this commit would advertise a mining interface version they do not implement. The commit is marked git-bisect-skip and warns against distributing or connecting such binaries. The final commit in the series is expected to bump the interface version to restore proper mismatch detection.
Changed components
src/ipc/capnp/mining.capnptest/functional/interface_ipc_mining.pytest/functional/test_framework/ipc_util.pyBitcoin Core IPC mining interfaceInspect captured patch +8 / −8
diff --git a/src/ipc/capnp/mining.capnp b/src/ipc/capnp/mining.capnp
index 0727fcc0..47cd242b 100644
--- a/src/ipc/capnp/mining.capnp
+++ b/src/ipc/capnp/mining.capnp
@@ -22,8 +22,8 @@ interface Mining $Proxy.wrap("interfaces::Mining") {
isInitialBlockDownload @1 (context :Proxy.Context) -> (result: Bool);
getTip @2 (context :Proxy.Context) -> (result: Common.BlockRef, hasResult: Bool);
waitTipChanged @3 (context :Proxy.Context, currentTip: Data, timeout: Float64 = .maxDouble) -> (result: Common.BlockRef);
- createNewBlock @4 (options: BlockCreateOptions) -> (result: BlockTemplate);
- checkBlock @5 (block: Data, options: BlockCheckOptions) -> (reason: Text, debug: Text, result: Bool);
+ createNewBlock @4 (context :Proxy.Context, options: BlockCreateOptions) -> (result: BlockTemplate);
+ checkBlock @5 (context :Proxy.Context, block: Data, options: BlockCheckOptions) -> (reason: Text, debug: Text, result: Bool);
}
interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
diff --git a/test/functional/interface_ipc_mining.py b/test/functional/interface_ipc_mining.py
index 0a530827..2221d462 100755
--- a/test/functional/interface_ipc_mining.py
+++ b/test/functional/interface_ipc_mining.py
@@ -242,7 +242,7 @@ class IPCMiningTest(BitcoinTestFramework):
self.log.debug("Enforce minimum reserved weight for IPC clients too")
opts.blockReservedWeight = 0
try:
- await mining.createNewBlock(opts)
+ await mining.createNewBlock(ctx, opts)
raise AssertionError("createNewBlock unexpectedly succeeded")
except capnp.lib.capnp.KjException as e:
if e.type == "DISCONNECTED":
@@ -269,7 +269,7 @@ class IPCMiningTest(BitcoinTestFramework):
current_block_height = self.nodes[0].getchaintips()[0]["height"]
check_opts = self.capnp_modules['mining'].BlockCheckOptions()
- async with destroying((await mining.createNewBlock(self.default_block_create_options)).result, ctx) as template:
+ async with destroying((await mining.createNewBlock(ctx, self.default_block_create_options)).result, ctx) as template:
block = await mining_get_block(template, ctx)
balance = self.miniwallet.get_balance()
coinbase = await self.build_coinbase_test(template, ctx, self.miniwallet)
@@ -282,7 +282,7 @@ class IPCMiningTest(BitcoinTestFramework):
self.log.debug("Submit a block with a bad version")
block.nVersion = 0
block.solve()
- check = await mining.checkBlock(block.serialize(), check_opts)
+ check = await mining.checkBlock(ctx, block.serialize(), check_opts)
assert_equal(check.result, False)
assert_equal(check.reason, "bad-version(0x00000000)")
submitted = (await template.submitSolution(ctx, block.nVersion, block.nTime, block.nNonce, coinbase.serialize())).result
@@ -292,7 +292,7 @@ class IPCMiningTest(BitcoinTestFramework):
block.solve()
self.log.debug("First call checkBlock()")
- block_valid = (await mining.checkBlock(block.serialize(), check_opts)).result
+ block_valid = (await mining.checkBlock(ctx, block.serialize(), check_opts)).result
assert_equal(block_valid, True)
# The remote template block will be mutated, capture the original:
@@ -324,7 +324,7 @@ class IPCMiningTest(BitcoinTestFramework):
self.miniwallet.rescan_utxos()
assert_equal(self.miniwallet.get_balance(), balance + 1)
self.log.debug("Check block should fail now, since it is a duplicate")
- check = await mining.checkBlock(block.serialize(), check_opts)
+ check = await mining.checkBlock(ctx, block.serialize(), check_opts)
assert_equal(check.result, False)
assert_equal(check.reason, "inconclusive-not-best-prevblk")
diff --git a/test/functional/test_framework/ipc_util.py b/test/functional/test_framework/ipc_util.py
index 2ab74aba..11497463 100644
--- a/test/functional/test_framework/ipc_util.py
+++ b/test/functional/test_framework/ipc_util.py
@@ -108,7 +108,7 @@ async def make_capnp_init_ctx(self):
async def mining_create_block_template(mining, stack, ctx, opts):
"""Call mining.createNewBlock() and return template, then call template.destroy() when stack exits."""
- response = await mining.createNewBlock(opts)
+ response = await mining.createNewBlock(ctx, opts)
if not response._has("result"):
return None
return await stack.enter_async_context(destroying(response.result, ctx))
Why this scored 25/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.