#10102 Multiprocess bitcoin

full analysis

https://github.com/bitcoin/bitcoin/pull/10102 · ryanofsky · +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

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:

ReviewerKindHarmStatusBlockingAuthor repliedQuote
gmaxwellapproachAdds Cap'n Proto dependency to the projectresolvednoyes2017-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
dcousensapproachPrefers reusing existing RPC instead of adding an external RPC/IPC frameworkresolvednoyes2017-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
electorrapproachOpposes the multiprocess conceptresolvednono2021-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
practicalswiftcorrectnesspotential dead pointer or use-after-free for loop_ptr if socket disconnected immediatelyresolvednoyes2018-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:

  • #19460
  • #19461
  • Multiprocess Bitcoin node, wallet, and GUI executable targets

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.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T21:15, confidence high, input hash d98b5fd2bf66a699