Skip to content

Conversation

sipa
Copy link
Member

@sipa sipa commented Aug 15, 2025

This adds support to the functional test framework to run the multiprocess bitcoin-node binary, and then tests it in a new interface_ipc.py functional test through the pycapnp module.

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 15, 2025

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33201.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK janb84
Stale ACK josibake, ismaelsadeeq, Sjors, ryanofsky

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #33142 (test: Run bench sanity checks in parallel with functional tests by maflcko)
  • #32297 (bitcoin-cli: Add -ipcconnect option by ryanofsky)
  • #31723 (qa debug: Add --debug_runs/-waitfordebugger [DRAFT] by hodlinator)
  • #30437 (ipc: add bitcoin-mine test program by ryanofsky)
  • #29838 (Feature: Use different datadirs for different signets by BrandonOdiwuor)

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 typos and grammar issues:

  • in test/README.md: “requires a python IPC library” -> “requires a Python IPC library” [“Python” is a proper noun]
  • in test/functional/interface_ipc.py comment: “have it’s own” -> “have its own” [possessive “its,” not contraction “it’s”]

No other comprehension-impacting typos were found.

drahtbot_id_4_m

@DrahtBot
Copy link
Contributor

🚧 At least one of the CI tasks failed.
Task lint: https://github.com/bitcoin/bitcoin/runs/48194727681
LLM reason (✨ experimental): The CI failure is caused by errors detected during the linting process, specifically from ruff and mypy, indicating code issues and missing module imports.

Hints

Try to run the tests locally, according to the documentation. However, a CI failure may still
happen due to a number of reasons, for example:

  • Possibly due to a silent merge conflict (the changes in this pull request being
    incompatible with the current code in the target branch). If so, make sure to rebase on the latest
    commit of the target branch.

  • A sanitizer issue, which can only be found by compiling with the sanitizer and running the
    affected test.

  • An intermittent issue.

Leave a comment here, if you need help tracking down a confusing failure.

@sipa sipa force-pushed the 202508_ipc_test branch from 5050855 to 27bd678 Compare August 15, 2025 20:24
@ryanofsky
Copy link
Contributor

Concept ACK. 27bd678 is really nice and simpler than I would have expected.

In case it's useful #30437 adds an interface_ipc_mining.py test, and #32297 adds an interface_ipc_cli.py test which are similar to this test and have similar test framework updates. Code from those PRs might be useful here or vice versa.

@sipa sipa force-pushed the 202508_ipc_test branch 4 times, most recently from b4cb8f6 to b87de46 Compare August 16, 2025 00:08
@Sjors
Copy link
Member

Sjors commented Aug 16, 2025

Concept ACK

So far I achieved test coverage for the Mining interface with a combination of unit tests and by having RPC methods such as getblocktemplate use the interface internally. But the latter has side-effects (see #32547) and could be avoided once we have enough direct coverage.

CentOS CI fails with capnp.lib.capnp.KjException: mp/proxy.capnp:6: failed: Import failed: /capnp/c++.capn https://cirrus-ci.com/task/4824947408764928?logs=ci#L3320

Copy link
Member

@Sjors Sjors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On macOS 15.6 with capnp 1.2.0 installed via Homebrew and Python 3.10.14 installed via PyEnv I get:

pip3 install pycapnp
...
Successfully installed pycapnp-2.0.0

cmake -B build
cmake --build build
...

% build/test/functional/interface_ipc.py
2025-08-17T07:05:49.321522Z TestFramework (INFO): PRNG seed is: 6039316184654231320
2025-08-17T07:05:49.322566Z TestFramework (INFO): Initializing test directory /var/folders/8p/qqdl2fsj7rd6q096jtmsfydc0000gn/T/bitcoin_func_test_z3jtr5u1
2025-08-17T07:05:50.595292Z TestFramework (ERROR): Unexpected exception
Traceback (most recent call last):
  File "/Users/sjors/dev/bitcoin/test/functional/test_framework/test_framework.py", line 200, in main
    self.run_test()
  File "/Users/sjors/dev/bitcoin/build/test/functional/interface_ipc.py", line 82, in run_test
    self.run_echo_test()
  File "/Users/sjors/dev/bitcoin/build/test/functional/interface_ipc.py", line 63, in run_echo_test
    asyncio.run(capnp.run(async_routine()))
  File "/Users/sjors/.pyenv/versions/3.10.14/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/Users/sjors/.pyenv/versions/3.10.14/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "capnp/lib/capnp.pyx", line 1944, in run
  File "capnp/lib/capnp.pyx", line 1945, in capnp.lib.capnp.run
  File "/Users/sjors/dev/bitcoin/build/test/functional/interface_ipc.py", line 57, in async_routine
    init, ctx = await self.make_capnp_init_ctx()
  File "/Users/sjors/dev/bitcoin/build/test/functional/interface_ipc.py", line 45, in make_capnp_init_ctx
    modules = self.capnp_modules()
  File "/Users/sjors/dev/bitcoin/build/test/functional/interface_ipc.py", line 38, in capnp_modules
    "proxy": capnp.load(str(mp_dir / "mp" / "proxy.capnp"), imports=imports),
  File "capnp/lib/capnp.pyx", line 4385, in capnp.lib.capnp.load
  File "capnp/lib/capnp.pyx", line 3574, in capnp.lib.capnp.SchemaParser.load
capnp.lib.capnp.KjException: mp/proxy.capnp:6: failed: Import failed: /capnp/c++.capnp

Maybe related: capnproto/pycapnp#377 (though pycapnp-1.3.0 doesn't work at all, since it doesn't have the run method)

Suggested test doc improvement:

diff --git a/test/README.md b/test/README.md
index 37f2c07217..3b2979cdf6 100644
--- a/test/README.md
+++ b/test/README.md
@@ -34,6 +34,9 @@ The ZMQ functional test requires a python ZMQ library. To install it:
 - on Unix, run `sudo apt-get install python3-zmq`
 - on mac OS, run `pip3 install pyzmq`

+The IPC functional test requires a python IPC library. To install it:
+
+- `pip3 install pycapnp`

 On Windows the `PYTHONUTF8` environment variable must be set to 1:

@sipa sipa force-pushed the 202508_ipc_test branch from 530ca0b to 088dc2c Compare August 19, 2025 15:14
Copy link
Member

@Sjors Sjors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 088dc2c (after base PR lands)

# as it is being called before knowing whether capnp is available).
self.capnp_modules = self.load_capnp_modules()

async def make_capnp_init_ctx(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

088dc2c: eventually I'd like to move this and load_capnp_modules into the test framework so that it's easier to expand e.g. mining_template_verification.py to call both getblocktemplate proposal and checkBlock().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving this for a follow-up.

@sipa
Copy link
Member Author

sipa commented Aug 19, 2025

Addressed a number of comments, and rebased on top of #31802.

I will however not have (much) time to push this further forward until the end of this month. @Sjors or @ryanofsky, or someone else, feel free to take this over and/or integrate into other PRs.

Copy link
Contributor

@janb84 janb84 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 088dc2c (after base #31802)

This PR adds some functional tests for the IPC interface, setups the CI to use IPC and changes build documentation to match the changes in this PR.

Current state of the PR works on nix on macOS, builds & test run without trouble.

  • build ✅
  • tested ✅
  • code review✅

small NIT if retouched, please see the remarks of DrahtBot's LLM linter.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review ACK 088dc2c. Looks great! Left some comments that you should feel free to ignore. I am shocked and amazed about how much more friendly the python async API is compared to the c++ API, but I guess coroutines can bring similar benefits to c++. It is also nice how this tests covers different scenarios with waitNext()

test/README.md Outdated
```sh
git clone https://github.com/capnproto/pycapnp.git`
cd pycapnp
pip install . -C force-bundled-libcapnp=True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "ci: add functional test for IPC interface" (088dc2c)

As mentioned #33201 (comment), would be curious to know if force-system-libcapnp=True works for people, since it seems wasteful to download and build a dependency that we already know must be installed (or the test would be skipped).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opted to use system libcapnp in the description here because it's more likely to work. I've added a comment about it being optional now.

Expose ENABLE_IPC build option to function tests so new tests can test IPC-only features.
Set new `BitcoinTestFramework.binary_paths.bitcoin_bin` property with path to
the `bitcoin` wrapper binary. This allows new tests for `bitcoin-mine` in
bitcoin#30437 and `bitcoin-cli` in bitcoin#32297 to find the `bitcoin` binary and call
`bitcoin -m` to start nodes with IPC support. This way the new tests can run
whenever the ENABLE_IPC build option is enabled, instead of only running when
the `BITCOIN_CMD` environment variable is set to `bitcoin -m`
With this change, tests can specify `self.extra_init = [{ipcbind: True}]` to
start a node listening on an IPC socket, instead of needing to choose which
node binary to invoke and what `self.extra_args=[["-ipcbind=..."]]` value to
pass to it.

The eliminates boilerplate code bitcoin#30437 (interface_ipc_mining.py), bitcoin#32297
(interface_ipc_cli.py), and bitcoin#33201 (interface_ipc.py) previously needed in
their test setup.
@Sjors
Copy link
Member

Sjors commented Aug 21, 2025

@sipa let me know if you don't have to time to rebase, in which case I'll open a fresh PR next week.

@sipa sipa force-pushed the 202508_ipc_test branch from 088dc2c to efa8b24 Compare August 21, 2025 07:20
@sipa
Copy link
Member Author

sipa commented Aug 21, 2025

Rebased, and addressed some of the feedback above.

Note that the last commit (which enables the tests in CI) may need work after moving to be on top of #31802, so that it matches the CI configurations which have IPC enabled.

@DrahtBot
Copy link
Contributor

🚧 At least one of the CI tasks failed.
Task lint: https://github.com/bitcoin/bitcoin/runs/48558512670
LLM reason (✨ experimental): Lint check failed due to unused variable capnp_bin.

Hints

Try to run the tests locally, according to the documentation. However, a CI failure may still
happen due to a number of reasons, for example:

  • Possibly due to a silent merge conflict (the changes in this pull request being
    incompatible with the current code in the target branch). If so, make sure to rebase on the latest
    commit of the target branch.

  • A sanitizer issue, which can only be found by compiling with the sanitizer and running the
    affected test.

  • An intermittent issue.

Leave a comment here, if you need help tracking down a confusing failure.

# Add the system cap'nproto path so include/capnp/c++.capnp can be found.
capnp_dir = Path(capnp_bin).parent.parent / "include"
else:
# If there is system cap'nproto, the pycapnp module should have it's own "bundled" includes at this location
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in test/functional/interface_ipc.py comment: “have it’s own” -> “have its own” [possessive “its,” not contraction “it’s”]

Copy link
Contributor

@janb84 janb84 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re ACK 03c66ee

changes since last ACK:

  • rebase
  • addressed some NIT's

@Sjors
Copy link
Member

Sjors commented Aug 21, 2025

For some reason on the macOS native job (00_setup_env_mac_native.sh) the interface test is skipped despite pycapnp being installed and bitcoin-node being built: https://github.com/bitcoin/bitcoin/actions/runs/17120162263/job/48559027457?pr=33201#step:8:3718

I checked that this test did run for native_asan.

I wrote a commit that enables it for additional jobs, which I'm testing in Sjors#101:

  • CentOS
  • native man
  • kernel
  • native_tsan
  • previous releases
  • native valgrind

Update: 0c88edc should be safe to cherry-pick, we can add the previous_release job later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants