mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-02-21 23:03:59 +01:00
ipc mining: pass missing context to BlockTemplate methods (incompatible schema change)
Adding a context parameter ensures that these methods are run in their own thread and don't block other calls. They were missing for: - createNewBlock() - checkBlock() The missing parameters were first pointed out by plebhash in https://github.com/bitcoin/bitcoin/issues/33575#issuecomment-3383290115 and adding them should prevent possible performance problems and lockups, especially with #34184 which can make the createNewBlock method block for a long time before returning. It would be straightforward to make this change in a backward compatible way (https://github.com/bitcoin/bitcoin/pull/34184#discussion_r2770232149) but nice to not need to go through the trouble. Warning: This is an intermediate, review-only commit. Binaries built from it should not be distributed or used to connect to other clients or servers. It makes incompatible changes to the `mining.capnp` schema without updating the `Init.makeMining` version, causing binaries to advertise support for a schema they do not actually implement. Mixed versions may therefore exchange garbage requests/responses instead of producing clear errors. The final commit in this series bumps the mining interface number to ensure mismatches are detected. git-bisect-skip: yes Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
This commit is contained in:
@@ -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") {
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user