#10102 Multiprocess bitcoin

ReviewabilityReviewsAgreementSize
#10102 ryanofsky Multiprocess bitcoinReview #29409 first0 (+1) -1Strong4,152 + 197 tests
  • Run Bitcoin Core node, wallet, and GUI components in isolated processes
  • Prevent memory corruption or crashes in the GUI or wallet from compromising or taking down the node
  • Broad support for the architectural direction of process separation (jonasschnelli, gmaxwell, dcousens, laanwj)
  • Concept approval citing ability to run the node continuously while opening the GUI on demand (Sjors)
  • Concerns over Cap'n Proto dependency were accepted as internal IPC for this change (gmaxwell, dcousens)
  • Open question on whether capnp should be added to depends in a future PR (Sjors)
  • 4,152 lines added or modified outside tests
  • 197 lines added or modified in tests
  • 634 lines removed in total
  • 146 files, 24 commits
IPC / multiprocess#3 of 18
P1 · new feature
  • P1 because process isolation prevents UI and wallet flaws from compromising consensus validation
  • Unblocks follow-up multiprocess architecture work across the codebase
  • Ranking pass: Kept P1 as the category-defining PR, but placed after the two prerequisites it is stacked on.
Wallet#34 of 92
P2 · new feature
  • P2 because running the wallet as an independent process shields the node from wallet crashes
  • Provides durable isolation against wallet-level memory corruption vulnerabilities
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:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
jonasschnelli (contributor)question, interfaceAsked whether RPC performance would be impractical, whether IPC could serve as a new general API, and whether authentication is supported or requiredanswered · author explained capnp is used for convenience, IPC is internal-only for now, and authentication is capability-basedansweredyes2017-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, scopeCould the IPC approach be designed as a new public API?answered · author explained intention is to keep IPC internal and transparentansweredyes2017-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, safetyDoes Cap'n Proto provide authentication and would it be required?answered · author explained authentication is not required for anonymous socketpair but supported via capabilitiesansweredyes2017-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, approachExpressed discomfort with adding Cap'n Proto dependencyanswered · laanwj noted that Cap'n Proto is fine for this PR's internal IPCansweredby others2017-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, approachPrefer using existing RPC instead of Cap'n Proto if feasibleanswered · laanwj urged avoiding serialization framework debates and accepted Cap'n Protoansweredby others2017-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, approachWhat 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 eventsansweredyes2017-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, approachWhat 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 satisfiedansweredyes2017-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, maintenanceShould capnp be added to depends in a future PR?openansweredno2018-08-11: 'Should capnp be added to depends (in a future PR) as well?'
practicalswift (contributor)objection, safetyloop_ptr could potentially be a dead pointer or cause use-after-free if socket disconnects immediatelyfixed · fix pushed · author moved onDisconnect handler down to fix potential dead pointerchangedyes2018-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

Depends on: #29409

Enables:

Based on (shares commits with): #29409

Base for: #19460, #19461

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

dossier JSON · extract JSON · model ledger, generated 2026-11-01T01:16, confidence high, input hash b10496e6c1f160b1
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