#10102 Multiprocess bitcoin
| Reviewability | Reviews | Agreement | Size | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| #10102 Multiprocess bitcoin | Review #29409 first | 0 (+1) -1 | Strong | 4,152 + 197 tests | ||||||
|
|
|
| |||||||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | ||||||||||
Goal
Enables Bitcoin Core to run as isolated processes by adding IPC wrappers for node and wallet interfaces using Cap'n Proto and libmultiprocess. When built with multiprocess support, bitcoin-gui spawns bitcoin-node as a child process, and bitcoin-node spawns bitcoin-wallet, communicating across socketpairs instead of running in a shared address space. Also updates the libmultiprocess subtree, exposes stable and unstable Chain interfaces over IPC, and makes btcsignals slot destruction eager on disconnect.
Problem: The node, wallet, and GUI components run within a single monolithic address space. A memory corruption vulnerability or crash in the GUI or wallet can compromise consensus validation or take down the entire node.
Evidence of importance:
- Description notes that running GUI, node, and wallet in separate processes allows 'relevant functionality isolated into different processes' so 'node, wallet, and GUI code run in separate address spaces for better isolation' (PR description and doc/multiprocess.md).
- Commit de0617691a notes concrete failure mode resolved by btcsignals changes: 'in multiprocess bitcoin-gui, where node notification callbacks own IPC proxy objects: their deferred destruction kept bitcoin-node from exiting and hung interface_gui.py until timeout.'
Scope: Very large change containing an update to the src/ipc/libmultiprocess git subtree, multiple new Cap'n Proto interface definitions, and core utility changes in btcsignals and interfaces::Init.
Risk of a mistake: medium (wallet, gui, build, other). A flaw in btcsignals callback destruction or IPC proxy synchronization could lead to deadlocks, use-after-free crashes, or hanging process terminations during node shutdown.
Changed since the previous assessment: Rebased onto #29409, updated the libmultiprocess subtree with upstream changes including platform compatibility fixes, introduced stable and unstable Chain IPC capnp wrappers, added an atomic_shared_ptr fallback in btcsignals for C++20 standard library variants lacking __cpp_lib_atomic_shared_ptr, and adjusted WalletLoader::restoreWallet parameter ordering.
Reviewability
Ready · Review #29409 first
Stacked on #29409; the base PR's changes are included in this diff.
Waiting on (from the thread read):
- author: answer Sjors' question on whether capnp should be added to depends 2018-08-11
Agreement
Strong
substantive support, no open objection (jonasschnelli, gmaxwell, dcousens, laanwj, Sjors, jimhashhq); NACK with no harm recorded (electorr)
Thread notes: Author documented a series of rebases and conflict resolutions up through commit pr/ipc.248 on top of base PR #29409; no new claims or reviews were added.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| jonasschnelli (contributor) | question, interface | Asked whether RPC performance would be impractical, whether IPC could serve as a new general API, and whether authentication is supported or required | answered · author explained capnp is used for convenience, IPC is internal-only for now, and authentication is capability-based | answered | yes | 2017-03-28: 'Three questions: - Would the performance be impractical if we would try to use the existing RPC API?' Status from: 2017-03-28: ryanofsky: 'Reason this is currently using capnp is not performance but convenience.' |
| jonasschnelli (contributor) | question, scope | Could the IPC approach be designed as a new public API? | answered · author explained intention is to keep IPC internal and transparent | answered | yes | 2017-03-28: 'Could the capnp approach (or lets say IPC approach) be designed as a (or the) new API ("JSON RPC v2" and replacement for ZMQ)?' Status from: 2017-03-28: ryanofsky: 'It could, but I'm going out of my way right now specifically NOT to add yet another bitcoind public API' |
| jonasschnelli (contributor) | question, safety | Does Cap'n Proto provide authentication and would it be required? | answered · author explained authentication is not required for anonymous socketpair but supported via capabilities | answered | yes | 2017-03-28: 'Does capnp provide a basic form of authentication? Would that even be required?' Status from: 2017-03-28: ryanofsky: 'It's not required here because this change doesn't expose any new socket or endpoint, but it could be supported.' |
| gmaxwell (contributor) | suggestion, approach | Expressed discomfort with adding Cap'n Proto dependency | answered · laanwj noted that Cap'n Proto is fine for this PR's internal IPC | answered | by others | 2017-03-28: 'I'm really uncomfortable with using capn proto, but fine enough for some example testing stuff!' Status from: 2017-03-29: laanwj: 'For this pull it's fine to use whatever RPC mechanism you're comfortable with.' |
| dcousens (contributor) | suggestion, approach | Prefer using existing RPC instead of Cap'n Proto if feasible | answered · laanwj urged avoiding serialization framework debates and accepted Cap'n Proto | answered | by others | 2017-03-28: 'strong concept ACK, but if is feasible, would prefer usage of the existing RPC instead of capn'proto' Status from: 2017-03-29: laanwj: 'Please, let's not turn this into a discussion of serialization and RPC frameworks... For this pull it's fine to use what' |
| sipa (member) | question, approach | What does moving to a separate process have to do with making GUI calls less blocking? | answered · author explained IPC allows updating one place instead of many to handle events | answered | yes | 2017-04-17: 'I don't understand what the move to a different process has to do with making things less blocking.' Status from: 2017-04-17: ryanofsky: 'With the IPC framework, there is only one place you have to update instead of 50 places' |
| sipa (member) | question, approach | What is the architectural purpose of separating GUI and daemon into separate processes if they still depend on each other? | accepted · author explained roadmap towards independent processes; sipa was satisfied | answered | yes | 2017-04-17: 'I don't understand the goal here. On itself, there seems little benefit in separating the GUI and the rest into separate processes if those two processes still depend on each other... what is the purp' Status from: 2017-04-17: sipa: 'Ok, that's what I was missing. It wasn't clear to me that this was a just first step towards a more useful separation.' |
| Sjors (member) | question, maintenance | Should capnp be added to depends in a future PR? | open | answered | no | 2018-08-11: 'Should capnp be added to depends (in a future PR) as well?' |
| practicalswift (contributor) | objection, safety | loop_ptr could potentially be a dead pointer or cause use-after-free if socket disconnects immediately | fixed · fix pushed · author moved onDisconnect handler down to fix potential dead pointer | changed | yes | 2018-09-04: 'Couldn't loop_ptr potentially be a dead pointer here?' Status from: 2018-09-04: ryanofsky: 'Good catch. It could happen if socket was immediately disconnected. Moved onDisconnect handler down to fix this.' |
Support:
- jonasschnelli (contributor) (2017-03-28) [read]: Conceptually I think this goes into the right direction
- gmaxwell (contributor) (2017-03-28): I'm a fan of this general approach (ignoring the use of capn proto) and I think we should have done something like it a long time ago.
- dcousens (contributor) (Concept ACK, 2017-03-28): strong concept ACK, but if is feasible, would prefer usage of the existing RPC instead of capn'proto
- laanwj (member) (Concept ACK, 2017-03-29) [read]: Concept ACK, nice... For this pull it's fine to use whatever RPC mechanism you're comfortable with. I'm also perfectly fine with keeping the scope here to 'communication between GUI and bitcoind'.
- Sjors (member) (Concept ACK, 2018-08-11) [tested]: Concept ACK, ultimately being able to leave bitcoin-node running while starting the GUI on demand, while not having to wait for sync, would be quite nice.
- jimhashhq (none) (2025-03-19) [tested]: I am in favor of a multiprocess Bitcoin, I find this a well considered change.
Participants:
- dcousens (contributor, support, 1 statements 2017-03-28 to 2017-03-28): Concept ACKed process separation; suggested using existing RPC instead of Cap'n Proto
- gmaxwell (contributor, support, 1 statements 2017-03-28 to 2017-03-28): supports general approach; suggested avoiding Cap'n Proto dependency
- jonasschnelli (contributor, support, 1 statements 2017-03-28 to 2017-03-28): supports process separation direction; asked about API scope and RPC alternatives
- laanwj (member, support, 14 statements 2017-03-29 to 2017-04-14): Concept ACKed process isolation and endorsed Cap'n Proto for internal IPC
- sipa (member, question, 3 statements 2017-04-17 to 2017-04-17): asked about the architectural purpose of process separation while processes remain coupled; satisfied by roadmap
- Sjors (member, support, 19 statements 2018-08-11 to 2023-05-08): Concept ACKed independent GUI execution and tested macOS builds; asked about capnp in depends
- practicalswift (contributor, objection, 34 statements 2018-09-02 to 2020-01-12): pointed out potential dead pointer in Cap'n Proto initialization
- leishman (contributor, neutral, 3 statements 2018-09-05 to 2018-09-05): code review comments on base PR commits
- fingera (contributor, neutral, 1 statements 2018-09-21 to 2018-09-21): reported GCC 7.3 build error
- ismail120572 (none, neutral, 1 statements 2018-11-02 to 2018-11-02): comment omitted
- jb55 (contributor, neutral, 2 statements 2019-05-26 to 2020-05-01): comment omitted
- jgarzik (contributor, support, 2 statements 2020-01-10 to 2020-09-13): Concept ACK recorded in omitted statements
- hebasto (member, support, 3 statements 2020-03-05 to 2020-06-02): Concept ACK recorded in omitted statements
- JeremyRubin (contributor, neutral, 2 statements 2020-05-01 to 2022-09-14): suggested splitting interface refactoring commits
- maflcko (member, neutral, 4 statements 2020-06-02 to 2023-09-21): comment omitted
- promag (contributor, support, 1 statements 2020-10-23 to 2020-10-23): Concept ACK recorded in omitted statements
- electorr (none, neutral, 1 statements 2021-03-04 to 2021-03-04): opposed concept in omitted statement without technical rationale
- fanquake (member, neutral, 1 statements 2021-03-12 to 2021-03-12): comment omitted
- ariard (contributor, neutral, 3 statements 2021-03-26 to 2022-04-12): comment omitted
- achow101 (member, neutral, 2 statements 2021-03-29 to 2022-10-17): comment omitted
- jonatack (member, neutral, 1 statements 2022-09-14 to 2022-09-14): comment omitted
- aureleoules (contributor, neutral, 1 statements 2022-09-15 to 2022-09-15): comment omitted
- jamesob (contributor, support, 1 statements 2022-10-25 to 2022-10-25): Concept ACK recorded in omitted statements
- atangangabbieian4 (none, neutral, 1 statements 2023-09-19 to 2023-09-19): comment omitted
- willcl-ark (member, neutral, 3 statements 2024-05-02 to 2024-06-14): comment omitted
- darosior (member, neutral, 1 statements 2024-12-03 to 2024-12-03): reported issue tracked upstream in libmultiprocess
- jimhashhq (none, support, 3 statements 2025-03-17 to 2025-03-20): tested builds and regtest; strongly in favor of multiprocess Bitcoin
- ViniciusCestarii (contributor, neutral, 1 statements 2026-08-14 to 2026-08-14): opened upstream PR in libmultiprocess to fix trailing whitespace
- sarkrezahoseinjisus-tech (none, neutral, 1 statements 2026-08-14 to 2026-08-14): empty comment
Dependencies
Files
236 lines under test/bench/ci.
- src/ipc/capnp/wallet.capnp +305/-0
- src/ipc/capnp/wallet.cpp +251/-0
- src/ipc/capnp/common-types.h +248/-2
- src/ipc/libmultiprocess/src/mp/util.cpp +216/-31
- src/ipc/capnp/chain.cpp +226/-0
- src/ipc/capnp/node.capnp +214/-0
- src/ipc/libmultiprocess/test/mp/test/test.cpp +208/-6
- src/ipc/libmultiprocess/test/mp/test/connect_tests.cpp +212/-0
- src/ipc/capnp/chain.capnp +207/-0
- src/ipc/libmultiprocess/src/mp/proxy.cpp +106/-47
- src/ipc/capnp/chain-types.h +128/-0
- src/ipc/libmultiprocess/test/mp/test/listen_tests.cpp +48/-77
- src/ipc/libmultiprocess/include/mp/proxy-io.h +79/-42
- src/ipc/capnp/node-types.h +110/-0
- src/ipc/capnp/node.cpp +97/-0
- src/ipc/libmultiprocess/src/mp/gen.cpp +48/-45
- src/init/bitcoin-wallet-ipc.cpp +84/-0
- src/ipc/libmultiprocess/test/mp/test/unixlistener.h +84/-0
- src/ipc/libmultiprocess/include/mp/util.h +63/-15
- src/util/btcsignals.h +65/-13
- src/test/btcsignals_tests.cpp +74/-0
- src/ipc/capnp/wallet-types.h +70/-0
- src/ipc/capnp/common.capnp +66/-0
- src/ipc/libmultiprocess/test/mp/test/foo.h +56/-1
- src/ipc/libmultiprocess/include/mp/proxy-types.h +40/-14
- src/ipc/libmultiprocess/include/mp/proxy.h +30/-23
- src/ipc/capnp/common.cpp +51/-0
- src/ipc/libmultiprocess/cmake/compat_config.cmake +0/-42
- src/ipc/capnp/init.cpp +40/-0
- src/ipc/capnp/node.h +40/-0
- src/ipc/libmultiprocess/include/mp/type-number.h +24/-15
- test/functional/test_framework/test_node.py +31/-8
- src/ipc/capnp/wallet.h +36/-0
- src/init/bitcoin-node.cpp +23/-12
- src/ipc/libmultiprocess/ci/scripts/ci.sh +34/-1
- src/ipc/libmultiprocess/.github/workflows/ci.yml +19/-14
- src/ipc/libmultiprocess/CMakeLists.txt +24/-9
- src/ipc/libmultiprocess/test/mp/test/spawn_tests.cpp +28/-5
- test/functional/interface_ipc.py +32/-0
- src/init/bitcoin-gui.cpp +8/-20
- src/ipc/CMakeLists.txt +28/-0
- src/ipc/libmultiprocess/test/mp/test/foo.capnp +28/-0
- src/ipc/capnp/common.h +27/-0
- src/ipc/libmultiprocess/include/mp/type-chrono.h +25/-2
- src/ipc/libmultiprocess/test/mp/test/common.h +27/-0
- src/ipc/capnp/init-types.h +25/-0
- src/ipc/libmultiprocess/include/mp/type-struct.h +12/-12
- src/ipc/libmultiprocess/cmake/iwyu-wrapper.sh +22/-0
- src/qt/bitcoin.cpp +18/-3
- src/ipc/libmultiprocess/include/mp/type-interface.h +10/-10
- src/ipc/libmultiprocess/shell.nix +13/-6
- src/ipc/libmultiprocess/include/mp/type-context.h +15/-3
- src/ipc/capnp/handler.capnp +17/-0
- CMakeLists.txt +14/-0
- src/ipc/capnp/context.h +14/-0
- src/ipc/libmultiprocess/.clang-tidy +12/-2
- src/node/interfaces.cpp +10/-4
- src/ipc/capnp/init.capnp +13/-0
- src/ipc/libmultiprocess/.github/workflows/bitcoin-core-ci.yml +8/-5
- src/ipc/libmultiprocess/example/calculator.cpp +4/-9
- src/ipc/libmultiprocess/example/printer.cpp +4/-9
- src/CMakeLists.txt +9/-3
- src/ipc/libmultiprocess/example/example.cpp +7/-5
- src/ipc/libmultiprocess/include/mp/type-char.h +9/-3
- test/functional/combine_logs.py +12/-0
- test/functional/feature_block.py +10/-2
- test/functional/wallet_multiwallet.py +6/-6
- src/ipc/capnp/handler-types.h +10/-0
- src/ipc/interfaces.cpp +6/-4
- src/ipc/libmultiprocess/ci/scripts/run.sh +6/-4
- src/ipc/libmultiprocess/doc/versions.md +8/-2
- src/ipc/libmultiprocess/include/mp/type-map.h +6/-4
- src/interfaces/chain.h +5/-4
- src/ipc/libmultiprocess/ci/configs/netbsd.bash +1/-7
- src/ipc/libmultiprocess/cmake/pthread_checks.cmake +8/-0
- src/ipc/libmultiprocess/include/mp/type-set.h +4/-4
- src/ipc/libmultiprocess/include/mp/type-threadmap.h +4/-4
- src/ipc/libmultiprocess/include/mp/type-unordered-set.h +4/-4
- src/ipc/libmultiprocess/include/mp/type-vector.h +4/-4
- src/wallet/init.cpp +8/-0
- test/functional/wallet_fast_rescan.py +4/-4
- test/functional/wallet_resendwallettransactions.py +4/-4
- src/ipc/libmultiprocess/ci/configs/olddeps.bash +5/-2
- src/ipc/libmultiprocess/test/mp/test/foo-types.h +7/-0
- doc/multiprocess.md +6/-0
- src/init/basic.cpp +3/-3
- src/ipc/libmultiprocess/ci/configs/newdeps.bash +6/-0
- src/ipc/libmultiprocess/doc/design.md +3/-3
- src/ipc/libmultiprocess/doc/usage.md +6/-0
- src/qt/test/apptests.h +5/-1
- src/util/result.h +5/-1
- src/wallet/imports.h +5/-1
- test/functional/wallet_groups.py +3/-3
- src/interfaces/ipc.h +4/-1
- src/ipc/context.h +5/-0
- src/ipc/libmultiprocess/include/mp/type-data.h +2/-3
- src/wallet/types.h +5/-0
- src/bitcoind.cpp +3/-1
- src/init.cpp +2/-2
- src/interfaces/init.h +3/-1
- src/interfaces/wallet.h +3/-1
- src/ipc/libmultiprocess/ci/configs/sanitize.bash +2/-2
- src/ipc/libmultiprocess/ci/scripts/config.sh +2/-2
- src/ipc/libmultiprocess/include/mp/type-string.h +3/-1
- src/qt/test/apptests.cpp +2/-2
- src/qt/walletcontroller.cpp +2/-2
- src/init/common.cpp +2/-1
- src/net.h +3/-0
- src/net_processing.h +3/-0
- src/wallet/coincontrol.h +3/-0
- test/lint/git-subtree-check.sh +2/-1
- contrib/devtools/circular-dependencies.py +1/-1
- doc/design/libraries.md +1/-1
- src/bitcoin-cli.cpp +1/-1
- src/init.h +1/-1
- src/init/common.h +1/-1
- src/ipc/libmultiprocess/ci/configs/default.bash +1/-1
- src/ipc/libmultiprocess/ci/configs/freebsd.bash +1/-1
- src/ipc/libmultiprocess/ci/configs/gnu32.bash +1/-1
- src/ipc/libmultiprocess/ci/configs/llvm.bash +1/-1
- src/ipc/libmultiprocess/ci/configs/macos.bash +1/-1
- src/ipc/libmultiprocess/ci/configs/openbsd.bash +1/-1
- src/ipc/libmultiprocess/cmake/TargetCapnpSources.cmake +1/-1
- src/ipc/libmultiprocess/doc/install.md +1/-1
- src/ipc/libmultiprocess/include/mp/type-function.h +1/-1
- src/ipc/libmultiprocess/include/mp/version.h +1/-1
- src/ipc/stub.cpp +1/-1
- src/netbase.h +2/-0
- src/qt/bitcoin.h +1/-1
- src/rpc/request.h +2/-0
- src/test/util/setup_common.cpp +1/-1
- src/wallet/interfaces.cpp +1/-1
- src/wallet/wallet.h +2/-0
- test/functional/wallet_createwallet.py +1/-1
- test/functional/wallet_descriptor.py +1/-1
- test/functional/wallet_encryption.py +1/-1
- test/functional/wallet_importdescriptors.py +1/-1
- test/functional/wallet_reorgsrestore.py +1/-1
- test/functional/wallet_startup.py +1/-1
- src/ipc/libmultiprocess/ci/README.md +1/-0
- src/ipc/libmultiprocess/include/mp/config.h.in +1/-0
- src/ipc/libmultiprocess/test/CMakeLists.txt +1/-0
- test/functional/feature_config_args.py +1/-0
- test/functional/feature_taproot.py +1/-0
- test/functional/test_framework/ipc_util.py +1/-0
- test/functional/wallet_transactiontime_rescan.py +1/-0
Card
The short text the ranking pass compares across PRs.
Adds multiprocess capability to Bitcoin Core, allowing bitcoin-gui, bitcoin-node, and bitcoin-wallet to run as separate isolated executables communicating via Cap'n Proto IPC over socketpairs. Currently, all components share a single address space, meaning a crash or vulnerability in wallet or GUI code can compromise the validating node. This PR represents the core implementation of the process separation project (#28722). It is based on #29409 and enables followup PRs #19460 and #19461.
Data
thread read through 2026-08-14 (195 statements), head f9458c6172
labels: GUI, RPC/REST/ZMQ, Needs rebase · draft
Categories
IPC / multiprocess
P1 · new feature (ranking pass: Kept P1 as the category-defining PR, but placed after the two prerequisites it is stacked on.)
This is the foundational multiprocess PR enabling process isolation across node, wallet, and GUI. As described, running GUI, node, and wallet in isolated processes ensures memory corruption or crashes in UI/wallet code cannot compromise consensus validation or crash the node, unblocking subsequent IPC work including #19460 and #19461.
Membership: Adds Cap'n Proto interface definitions, libmultiprocess updates, and multiprocess wrappers for node and wallet.
Factors: security/stability 2, bug 0, performance 0, user value 2, leverage 3
Wallet
P2 · new feature
Extracts wallet execution into an isolated process communicating over IPC. Running bitcoin-wallet outside the node process provides durable architectural isolation against memory corruption and unhandled crashes taking down the node.
Membership: Implements bitcoin-wallet-ipc and exports wallet interfaces across the IPC boundary in src/wallet/interfaces.cpp and wallet.capnp.
Factors: security/stability 2, bug 0, performance 0, user value 2, leverage 3