#10102 Multiprocess bitcoin
https://github.com/bitcoin/bitcoin/pull/10102 · · +3977/-539 in 136 files, 23 commits · labels: GUI, RPC/REST/ZMQ · draft
Goal
- Isolate the node, wallet, and GUI into separate processes so crashes or exploits do not compromise the node
- Allow components to run on independent lifecycles for improved stability and security
Adds an optional `--enable-multiprocess` build mode that splits Bitcoin Core into separate `bitcoin-node`, `bitcoin-wallet`, and `bitcoin-gui` executables communicating over IPC via Cap'n Proto and libmultiprocess. It introduces the Init IPC interface to spawn subprocesses across socket pairs, wraps the Node and Wallet interfaces, and updates `btcsignals` callback destruction semantics.
Problem: Monolithic architecture links the node, wallet, and GUI into single processes, causing GUI hangs when long operations hold core locks, and limiting security boundaries between consensus validation and wallet key management.
Category: IPC / multiprocess (#1 of 20)
P2 · new feature
- P1 because it delivers the executables needed to run the node, wallet, and GUI in separate processes
- It provides the core milestone for the multi-year process separation effort
- It unblocks downstream pull requests for isolated process execution
P2 because this is the milestone PR implementing the process-separation architecture for Bitcoin Core (tracking issue #28722). It provides the executables for running node, wallet, and GUI in separate processes and unblocks follow-up connection PRs #19460 and #19461.
Membership: Implements the core process-separation mechanism and Cap'n Proto wrappers for Node and Wallet interfaces.
Factors: security/stability 2, bug 0, performance 1, user value 2, leverage 3
Category: RPC / REST / ZMQ (#52 of 52)
P4 · cleanup
- P4 because the RPC changes are limited to passing a logging suffix in bitcoin-cli's MakeBasicInit call and adding a comment note in rpc/request.h. No RPC commands, schemas, or server mechanisms are modified.
P4 because the RPC changes are limited to passing a logging suffix in bitcoin-cli's MakeBasicInit call and adding a comment note in rpc/request.h. No RPC commands, schemas, or server mechanisms are modified.
Membership: Touches src/bitcoin-cli.cpp and src/rpc/request.h and carries the RPC/REST/ZMQ label.
Factors: security/stability 0, bug 0, performance 0, user value 0, leverage 0
Category: Utilities (logging, arguments, libraries) (#27 of 66)
P3 · bug fix
- P3 because it prevents callback state from being retained indefinitely after disconnect
- It eliminates test hangs and delays when shutting down processes
P3 because commit d5c694a fixes callback destruction timing in btcsignals to destroy slots eagerly upon disconnect rather than leaking or deferring until the next connect call. This prevents unpredictable resource lifetime issues across general node signal callbacks.
Membership: Substantively improves src/util/btcsignals.h and src/util/result.h, including unit test coverage.
Factors: security/stability 1, bug 1, performance 0, user value 0, leverage 1
Reviewability: Ready: Review #29409 first
- Review #29409 first
The code and CI are clean and passing, but the branch is stacked on top of open PR #29409 ('multiprocess: Add capnp wrapper for Chain interface').
Author status: Active; continuously rebasing and keeping stack updated across 100+ pushes.
Resolved concerns:
- Cap'n Proto serialization choice questioned in favor of JSON-RPC or P2P; resolved as Cap'n Proto is encapsulated internally and supports bidirectional asynchronous calls.
- Btcsignals callback destruction timing previously kept proxies alive indefinitely until next connection; resolved by implementing eager callback destruction on disconnect.
Agreement: Strong
- Strong long-standing concept consensus across multiple maintainers
- Concept approval emphasizing the value of process isolation (laanwj)
- Concept approval with testing (Sjors)
- Historical concept approval (dcousens, promag, jamesob, hebasto)
Strong concept ACK across multiple maintainers; early protocol objections resolved.
Maintainers and contributors broadly support the multiprocess architecture. Early debates over serialization frameworks resolved with agreement that internal Cap'n Proto usage is acceptable.
- laanwj (2017-03-29): 'Concept ACK, nice... For this pull it's fine to use whatever RPC mechanism you're comfortable with.'
- Sjors (2018-08-11): 'Concept ACK, ultimately being able to leave bitcoin-node running while starting the GUI on demand... would be quite nice.'
Objections:
| Reviewer | Kind | Harm | Status | Blocking | Author replied | Quote |
|---|---|---|---|---|---|---|
| gmaxwell | approach | Adds Cap'n Proto dependency to the project | resolved | no | yes | 2017-03-28: 'I\'m really uncomfortable with using capn proto, but fine enough for some example testing stuff!' Settled: 2017-03-29: laanwj noted 'For this pull it\'s fine to use whatever RPC mechanism you\'re comfortable with' and discussion moved on |
| dcousens | approach | Prefers reusing existing RPC instead of adding an external RPC/IPC framework | resolved | no | yes | 2017-03-28: 'strong concept ACK, but if is feasible, would prefer usage of the existing RPC instead of capn\'proto' Settled: 2017-03-28: author explained capnp provides bidirectional async calls without packing boilerplate and dcousens did not push back |
| electorr | approach | Opposes the multiprocess concept | resolved | no | no | 2021-03-04: concept_nack recorded from electorr without concrete technical argument Settled: 2021-03-04: unexplained single comment from non-contributor remained inactive while project maintainers continued progress |
| practicalswift | correctness | potential dead pointer or use-after-free for loop_ptr if socket disconnected immediately | resolved | no | yes | 2018-09-04: "Couldn't loop_ptr potentially be a dead pointer here?" Settled: 2018-09-04: "Good catch. It could happen if socket was immediately disconnected. Moved onDisconnect handler down to fix this." |
Support:
- laanwj: Endorsed process separation between bitcoind and GUI, and approved Cap'n Proto for internal use
- Sjors: Wanted independent GUI startup without waiting for sync and tested builds on macOS
- jimhashhq: Confirmed successful build and interactive regtest runs on Linux
- jgarzik: Concept ACK [not substantive]
- hebasto: Concept ACK [not substantive]
- promag: Concept ACK [not substantive]
- jamesob: Concept ACK [not substantive]
- gmaxwell: A fan of the general approach and thinks process separation should have been done a long time ago
- dcousens: Strong concept ACK for process separation [not substantive]
- jonasschnelli: Conceptually goes in the right direction [not substantive]
Participants: jonasschnelli (support), gmaxwell (objection), dcousens (objection), laanwj (support), sipa (question), Sjors (support), practicalswift (objection), leishman (question), fingera (neutral), ismail120572 (neutral), jb55 (neutral), jgarzik (support), hebasto (support), JeremyRubin (support), maflcko (neutral), promag (support), electorr (objection), fanquake (neutral), ariard (neutral), achow101 (neutral), jonatack (neutral), aureleoules (neutral), jamesob (support), atangangabbieian4 (neutral), willcl-ark (neutral), darosior (neutral), jimhashhq (support), sarkrezahoseinjisus-tech (neutral), ViniciusCestarii (support)
State derived from the lists: substantive support, no open objection (laanwj, Sjors, jimhashhq, gmaxwell)
Review verdicts (DrahtBot): 0 (+1) -1
Dependencies
Depends on: #29409
Enables:
Based on (shares commits with): #29409
Base for: #19460, #19461
Files
173 lines under test/bench/ci.
- src/ipc/capnp/wallet.capnp +269/-0
- src/ipc/capnp/common-types.h +251/-2
- src/ipc/capnp/wallet.cpp +251/-0
- src/ipc/libmultiprocess/src/mp/util.cpp +216/-31
- src/ipc/capnp/node.capnp +213/-0
- src/ipc/libmultiprocess/test/mp/test/connect_tests.cpp +212/-0
- src/ipc/capnp/chain.cpp +208/-0
- src/ipc/libmultiprocess/test/mp/test/test.cpp +190/-6
- src/ipc/capnp/chain.capnp +189/-0
- src/ipc/libmultiprocess/src/mp/proxy.cpp +94/-35
- src/ipc/libmultiprocess/test/mp/test/listen_tests.cpp +47/-77
- src/ipc/capnp/chain-types.h +112/-0
- src/ipc/capnp/node-types.h +110/-0
- src/ipc/libmultiprocess/include/mp/proxy-io.h +74/-28
- src/ipc/capnp/node.cpp +97/-0
- src/init/bitcoin-wallet-ipc.cpp +84/-0
- src/ipc/capnp/common.capnp +84/-0
- src/ipc/libmultiprocess/test/mp/test/unixlistener.h +84/-0
- src/ipc/libmultiprocess/src/mp/gen.cpp +39/-41
- src/ipc/libmultiprocess/include/mp/util.h +63/-15
- src/util/btcsignals.h +69/-9
- src/ipc/capnp/wallet-types.h +55/-0
- src/ipc/capnp/common.cpp +51/-0
- src/test/btcsignals_tests.cpp +46/-0
- src/ipc/libmultiprocess/include/mp/proxy-types.h +31/-12
- 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/test/mp/test/spawn_tests.cpp +28/-5
- src/ipc/libmultiprocess/test/mp/test/foo.h +31/-1
- src/init/bitcoin-gui.cpp +8/-20
- 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/.github/workflows/ci.yml +15/-9
- src/ipc/libmultiprocess/CMakeLists.txt +17/-7
- src/ipc/libmultiprocess/include/mp/type-struct.h +12/-12
- src/qt/bitcoin.cpp +18/-3
- src/ipc/libmultiprocess/include/mp/type-interface.h +10/-10
- src/ipc/CMakeLists.txt +19/-0
- src/ipc/libmultiprocess/ci/scripts/ci.sh +18/-0
- src/ipc/libmultiprocess/include/mp/type-context.h +15/-3
- src/ipc/libmultiprocess/shell.nix +12/-6
- src/ipc/capnp/handler.capnp +17/-0
- CMakeLists.txt +14/-0
- src/ipc/capnp/context.h +14/-0
- src/ipc/libmultiprocess/include/mp/proxy.h +8/-6
- src/node/interfaces.cpp +10/-4
- 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
- src/ipc/libmultiprocess/test/mp/test/foo.capnp +12/-0
- 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/doc/versions.md +8/-2
- src/interfaces/chain.h +5/-4
- src/ipc/capnp/init.capnp +9/-0
- src/ipc/libmultiprocess/ci/configs/netbsd.bash +1/-7
- src/ipc/libmultiprocess/cmake/pthread_checks.cmake +8/-0
- src/ipc/libmultiprocess/include/mp/type-threadmap.h +4/-4
- src/wallet/init.cpp +8/-0
- test/functional/wallet_fast_rescan.py +4/-4
- test/functional/wallet_resendwallettransactions.py +4/-4
- doc/multiprocess.md +6/-0
- src/init/basic.cpp +3/-3
- src/ipc/libmultiprocess/ci/configs/newdeps.bash +6/-0
- src/ipc/libmultiprocess/doc/usage.md +6/-0
- src/ipc/libmultiprocess/test/mp/test/foo-types.h +6/-0
- src/qt/test/apptests.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/ci/configs/olddeps.bash +4/-1
- 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/doc/design.md +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/ipc/libmultiprocess/.github/workflows/bitcoin-core-ci.yml +3/-0
- 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/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/type-map.h +2/-0
- src/ipc/libmultiprocess/include/mp/version.h +1/-1
- src/ipc/stub.cpp +1/-1
- src/netbase.h +2/-0
- src/policy/fees/block_policy_estimator.h +2/-0
- src/qt/bitcoin.h +1/-1
- src/rpc/request.h +2/-0
- src/test/util/setup_common.cpp +1/-1
- src/util/result.h +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
- src/ipc/libmultiprocess/.clang-tidy +1/-0
- 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/wallet_transactiontime_rescan.py +1/-0
Card
This PR adds the `--enable-multiprocess` build flag, allowing Bitcoin Core to run `bitcoin-node`, `bitcoin-wallet`, and `bitcoin-gui` as separate processes communicating over Cap'n Proto IPC. It addresses process isolation between consensus validation, wallet key handling, and the GUI interface, eliminating GUI thread lock contention and laying the groundwork for privilege separation. There is strong long-term maintainer support for the multiprocess initiative, though the PR is based on open base PR #29409, which should be reviewed first.