test: Add IPC wake-up test and reuse mining context#34727
test: Add IPC wake-up test and reuse mining context#34727enirox001 wants to merge 4 commits intobitcoin:masterfrom
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please copy-paste ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. LLM Linter (✨ experimental)Possible places where named args for integral literals may be used (e.g.
2026-03-13 10:39:37 |
c57da9f to
1329a7d
Compare
6c4c62d to
79d3f77
Compare
ca5fdb5 to
3477c43
Compare
|
Added a new test in 3477c43 to verify that Also updated the PR description to match changes |
ryanofsky
left a comment
There was a problem hiding this comment.
Code review ACK 3477c43. Nice changes, and thanks for following up on the previous PRs! I'm a little unsure about the cost/benefit of the new createNewBlock cooldown test and asked some questions, and would like @Sjors to weigh in on. But it seems reasonable and the other test and refactoring changes both look good
|
Concept ACK |
b46dd5a to
daf405d
Compare
daf405d to
730b93a
Compare
|
Thanks for the reviews, @ryanofsky and @Sjors I've pushed an update addressing the recent review feedback.
|
| results['success'] = res._has("result") | ||
| task = asyncio.create_task(create_block_with_timing()) | ||
| block_hex = self.nodes[1].getblock(node1_block_hash, False) | ||
| self.nodes[0].submitblock(block_hex) |
There was a problem hiding this comment.
251c9fe: omitting this line does not cause the test to fail.
There was a problem hiding this comment.
In commit "test: verify createNewBlock wakes promptly when tip advances" (251c9fe)
re: #34727 (comment)
251c9fe: omitting this line does not cause the test to fail.
Not sure but maybe the test is forgetting to disconnect the nodes, so the block is getting synced even though it is not submitted?
The test also seems off in a few other ways. For one thing, it would seem nice if the test could use the wait_and_do helper. I would think the createNewBlock call go in the async wait_fn and submitblock and setmocktime could go in a do_fn.
The comment about a 10-second timeout as padding doesn't seem right to me, because I would expect that after the block is submitted, there is still an additional cooldown period like 3 seconds or whatever before createNewBlock returns, and the point of the mocktime call would be to advance by 3 seconds so the test does not need to wait.
It also doesn't seem like there is a point to the time.time() calls and the 'duration' value seems to be set and never used. The result dict could also be replaced by using python's nonlocal keyword.
Sorry for all the suggestions, it just seems like there a number of things that could be improved
There was a problem hiding this comment.
Thanks for the suggestions! I've completely refactored this:
- Applied
wait_and_doandnonlocalto clean up the structure. - Removed the confusing 10-second padding comment.
- Regarding mocktime/duration: I tested it, and the internal 3-second wait relies on the real-time system clock, so
setmocktimedoesn't bypass it. Because the node naturally returns after 3 seconds anyway, I kept thetime.time()check to assert duration < 3.0
| results['success'] = res._has("result") | ||
| task = asyncio.create_task(create_block_with_timing()) | ||
| block_hex = self.nodes[1].getblock(node1_block_hash, False) | ||
| self.nodes[0].submitblock(block_hex) |
There was a problem hiding this comment.
In commit "test: verify createNewBlock wakes promptly when tip advances" (251c9fe)
re: #34727 (comment)
251c9fe: omitting this line does not cause the test to fail.
Not sure but maybe the test is forgetting to disconnect the nodes, so the block is getting synced even though it is not submitted?
The test also seems off in a few other ways. For one thing, it would seem nice if the test could use the wait_and_do helper. I would think the createNewBlock call go in the async wait_fn and submitblock and setmocktime could go in a do_fn.
The comment about a 10-second timeout as padding doesn't seem right to me, because I would expect that after the block is submitted, there is still an additional cooldown period like 3 seconds or whatever before createNewBlock returns, and the point of the mocktime call would be to advance by 3 seconds so the test does not need to wait.
It also doesn't seem like there is a point to the time.time() calls and the 'duration' value seems to be set and never used. The result dict could also be replaced by using python's nonlocal keyword.
Sorry for all the suggestions, it just seems like there a number of things that could be improved
730b93a to
400f927
Compare
400f927 to
9b6985c
Compare
|
Thanks for the detailed review again I pushed an update addressing the recent review feedback. Regarding the changes i really wanted to use I tried advancing Because of this, a standard timeout wouldn't catch a failure if the If there is a way to making |
|
CI failure is unrelated |
| self.nodes[0].submitblock(block_hex) | ||
| await wait_and_do(wait_fn(), do_fn) | ||
| assert_equal(success, True) | ||
| assert duration < 3.0, f"createNewBlock took {duration:.2f}s, did not wake up promptly after tip advances" |
There was a problem hiding this comment.
3d81147: on my M4 MacBook Pro duration was 0.118s on average, of which 0.1 is from wait_and_do. So we have 3 / (0.118 - 0.1) = 160x margin for a very slow CI machine. So the odds a false positive failure seem acceptably low.
|
If you feel like adding another followup commit, it would be good to scale waits (waitNext, etc) with the test suite timeout scaling factor. For background see bitcoin-core/libmultiprocess#253 (comment) |
Sounds good, would work to add a followup commit with these changes |
9b6985c to
6865cc4
Compare
This adds a complementary test to interface_ipc_mining.py to ensure that createNewBlock() wakes up immediately once submitblock advances the tip, rather than needlessly waiting for the cooldown timer to expire on its own.
The async routines in both interface_ipc.py and interface_ipc_mining.py contain redundant code to initialize the mining proxy object. Move the make_mining_ctx helper into test_framework/ipc_util.py and update both test files to use it. This removes the boilerplate and prevents code duplication across the IPC test suite.
Add a test case to interface_ipc_mining.py to verify that the IPC server correctly handles and reports serialization errors rather than crashing the node. This covers the scenario where submitSolution is called with data that cannot be deserialized, as discussed in bitcoin#33341 Also introduces the assert_capnp_failed helper in ipc_util.py to cleanly handle macOS-specific Cap'n Proto exception strings, and refactors an existing block weight test to use it.
6865cc4 to
f65687b
Compare
| self.log.debug("interrupt() should abort waitTipChanged()") | ||
| async def wait_for_tip(): | ||
| long_timeout = 60000.0 # 1 minute | ||
| long_timeout = 60000.0 * self.options.timeout_factor # 1 minute |
There was a problem hiding this comment.
This might be a bit much, depending on the maximum timeout factor used in CI - it might exceed the test runner max run time. If so, we could e.g. use the max of 1000 * timeout, 60000.
There was a problem hiding this comment.
You're right, a massive timeout factor would definitely nuke the CI runner with a really long wait. I've updated this to use max(timeout, 60000.0) so it defaults to a safe 1 minute. I also applied the same max() fix to the timeout * 60 line later in the file to make sure it doesn't cause the same hang.
The IPC mining tests (interface_ipc_mining.py) currently use hardcoded timeouts (e.g., 1000ms, 60000ms) for operations like waitTipChanged and waiting for block templates. In heavily loaded CI environments, such as those running sanitizers with high parallelism, these hardcoded timeouts can be too short, leading to spurious test failures and brittleness. This commit multiplies these timeout variables by the test suite's global `self.options.timeout_factor`. This ensures that the IPC wait conditions scale appropriately when the test suite is run with a higher timeout factor, making the tests robust against slow execution environments. Addresses CI brittleness observed in bitcoin-core/libmultiprocess#253.
25e6fdc to
9a71d53
Compare
|
Thanks for the feedback and reviews. I've pushed an update addressing the recent reviews:
Updated PR description as well |
|
Thanks! ACK 9a71d53 |
This is a follow-up to implement a couple of test improvements discussed in recent IPC PRs and issues.
interface_ipc_mining.pyto verify thatcreateNewBlockwakes up immediately when the tip advances, rather than waiting for the cooldown timer to expire (mining: add cooldown to createNewBlock() immediately after IBD #34184 (comment)).make_mining_ctxintoipc_util.pyso it can be reused across the IPC tests instead of duplicating the setup code (Update libmultiprocess subtree to be more stable with rust IPC client #34422 (comment)).submitSolutionreturns a remote exception instead of crashing the node, closing the loop on the issue reported in ipc: crash onsubmitSolutioncall with invalid coinbase #33341.timeout_factorto prevent spurious failures in heavily loaded CI environments, capping extended waits to avoid test runner hangs (ci: run some Bitcoin Core CI jobs bitcoin-core/libmultiprocess#253 (comment)).