Skip to content

Commit 7d9e3ef

Browse files
committed
ipc # Multiprocess bitcoin
Multiprocess bitcoin This change only affects bitcoin-node, bitcoin-wallet, and bitcoin-gui executables, which aren't built by default (they can be enabled with the --enable-multiprocess autoconf option). Normal bitcoind and bitcoin-qt build outputs are unaffected by this change. After this change, bitcoin-gui will spawn a bitcoin-node process, and bitcoin-node will spawn a bitcoin-wallet process. The processes communicate across socket pairs so gui, node, and wallet functionality is segregated into respective processes. The IPC calls can be seen running with -debug=ipc. See doc/multiprocess.md for details. Work in progress, many improvements and cleanups are needed (see FIXMEs)
1 parent f77ac4e commit 7d9e3ef

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2430
-63
lines changed

build_msvc/bitcoin-qt/bitcoin-qt.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
</PropertyGroup>
1010
<ItemGroup>
1111
<ClCompile Include="..\..\src\qt\main.cpp" />
12+
<ClCompile Include="..\..\src\init\bitcoin-qt.cpp" />
1213
<ResourceCompile Include="..\..\src\qt\res\bitcoin-qt-res.rc" />
1314
</ItemGroup>
1415
<ItemGroup>

build_msvc/bitcoin-wallet/bitcoin-wallet.vcxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
</PropertyGroup>
1111
<ItemGroup>
1212
<ClCompile Include="..\..\src\bitcoin-wallet.cpp" />
13+
<ClCompile Include="..\..\src\init\bitcoin-wallet.cpp">
14+
<ObjectFileName>$(IntDir)init_bitcoin-wallet.obj</ObjectFileName>
15+
</ClCompile>
1316
</ItemGroup>
1417
<ItemGroup>
1518
<ProjectReference Include="..\libbitcoinconsensus\libbitcoinconsensus.vcxproj">

build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
99
</PropertyGroup>
1010
<ItemGroup>
11+
<ClCompile Include="..\..\src\init\bitcoin-qt.cpp" />
1112
<ClCompile Include="..\..\src\test\util\setup_common.cpp" />
1213
<ClCompile Include="..\..\src\qt\test\addressbooktests.cpp" />
1314
<ClCompile Include="..\..\src\qt\test\apptests.cpp" />

contrib/devtools/circular-dependencies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# define functions and variables declared in corresponding .h files is
1717
# incorrect.
1818
HEADER_MODULE_PATHS = [
19-
'interfaces/'
19+
'ipc/'
2020
]
2121

2222
def module_name(path):

doc/multiprocess.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
On unix systems, the `--enable-multiprocess` build option can be passed to `./configure` to build new `bitcoin-node`, `bitcoin-wallet`, and `bitcoin-gui` executables alongside existing `bitcoind` and `bitcoin-qt` executables.
44

5-
`bitcoin-node` is a drop-in replacement for `bitcoind`, and `bitcoin-gui` is a drop-in replacement for `bitcoin-qt`, and there are no differences in use or external behavior between the new and old executables. But internally (after [#10102](https://github.com/bitcoin/bitcoin/pull/10102)), `bitcoin-gui` will spawn a `bitcoin-node` process to run P2P and RPC code, communicating with it across a socket pair, and `bitcoin-node` will spawn `bitcoin-wallet` to run wallet code, also communicating over a socket pair. This will let node, wallet, and GUI code run in separate address spaces for better isolation, and allow future improvements like being able to start and stop components independently on different machines and environments.
5+
`bitcoin-node` is a drop-in replacement for `bitcoind`, and `bitcoin-gui` is a drop-in replacement for `bitcoin-qt`, and there are no differences in use or external behavior between the new and old executables. But internally `bitcoin-gui` will spawn a `bitcoin-node` process to run P2P and RPC code, communicating with it across a socket pair, and `bitcoin-node` will spawn `bitcoin-wallet` to run wallet code, also communicating over a socket pair. This lets node, wallet, and GUI code run in separate address spaces for better isolation, and allow future improvements like being able to start and stop components independently on different machines and environments.
66

77
## Next steps
88

9-
Specific next steps after [#10102](https://github.com/bitcoin/bitcoin/pull/10102) will be:
10-
119
- [ ] Adding `-ipcbind` and `-ipcconnect` options to `bitcoin-node`, `bitcoin-wallet`, and `bitcoin-gui` executables so they can listen and connect to TCP ports and unix socket paths. This will allow separate processes to be started and stopped any time and connect to each other.
1210
- [ ] Adding `-server` and `-rpcbind` options to the `bitcoin-wallet` executable so wallet processes can handle RPC requests directly without going through the node.
1311
- [ ] Supporting windows, not just unix systems. The existing socket code is already cross-platform, so the only windows-specific code that needs to be written is code spawning a process and passing a socket descriptor. This can be implemented with `CreateProcess` and `WSADuplicateSocket`. Example: https://memset.wordpress.com/2010/10/13/win32-api-passing-socket-with-ipc-method/.
@@ -34,6 +32,12 @@ The configure script will pick up settings and library locations from the depend
3432

3533
Alternately, you can install [Cap'n Proto](https://capnproto.org/) and [libmultiprocess](https://github.com/chaincodelabs/libmultiprocess) packages on your system, and just run `./configure --enable-multiprocess` without using the depends system. The configure script will be able to locate the installed packages via [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/). See [Installation](https://github.com/chaincodelabs/libmultiprocess#installation) section of the libmultiprocess readme for install steps. See [build-unix.md](build-unix.md) and [build-osx.md](build-osx.md) for information about installing dependencies in general.
3634

35+
## Known issues
36+
37+
- Unexpected socket disconnects aren't handled cleanly many places. Interface calls that used to never throw can now throw exceptions if a socket is disconnected (typically because a process on the other side of the connection has crashed or been killed), leading to errors.
38+
39+
- Internally spawned bitcoin-node and bitcoin-wallet processes don't currently install signal handlers and so won't shut down cleanly if terminated with [CTRL-C](https://github.com/bitcoin/bitcoin/pull/10102#issuecomment-595353238). Shutting down with `bitcoin-cli stop` should still shut down cleanly, and is a suggested alternative.
40+
3741
## IPC implementation details
3842

3943
Cross process Node, Wallet, and Chain interfaces are defined in

src/Makefile.am

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,10 @@ obj/build.h: FORCE
302302
"$(abs_top_srcdir)"
303303
libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
304304

305+
# Explicitly list dependencies on generated headers as described
306+
# https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually
305307
ipc/capnp/libbitcoin_ipc_a-ipc.$(OBJEXT): $(libbitcoin_ipc_mpgen_input:=.h)
308+
ipc/capnp/libbitcoin_ipc_a-chain.$(OBJEXT): $(libbitcoin_ipc_mpgen_input:=.h)
306309

307310
# server: shared between bitcoind and bitcoin-qt
308311
# Contains code accessing mempool and chain state that is meant to be separated
@@ -649,7 +652,7 @@ bitcoin_node_SOURCES = $(bitcoin_daemon_sources) init/bitcoin-node.cpp
649652
bitcoin_node_CPPFLAGS = $(bitcoin_bin_cppflags)
650653
bitcoin_node_CXXFLAGS = $(bitcoin_bin_cxxflags)
651654
bitcoin_node_LDFLAGS = $(bitcoin_bin_ldflags)
652-
bitcoin_node_LDADD = $(LIBBITCOIN_SERVER) $(bitcoin_bin_ldadd) $(LIBBITCOIN_IPC) $(LIBMULTIPROCESS_LIBS)
655+
bitcoin_node_LDADD = $(LIBBITCOIN_SERVER) $(bitcoin_bin_ldadd) $(LIBBITCOIN_IPC) $(LIBBITCOIN_WALLET) $(LIBMULTIPROCESS_LIBS)
653656

654657
# bitcoin-cli binary #
655658
bitcoin_cli_SOURCES = bitcoin-cli.cpp
@@ -693,10 +696,15 @@ bitcoin_tx_LDADD += $(BOOST_LIBS)
693696

694697
# bitcoin-wallet binary #
695698
bitcoin_wallet_SOURCES = bitcoin-wallet.cpp
699+
if BUILD_MULTIPROCESS
700+
bitcoin_wallet_SOURCES += init/bitcoin-wallet-ipc.cpp
701+
else
702+
bitcoin_wallet_SOURCES += init/bitcoin-wallet.cpp
703+
endif
696704
bitcoin_wallet_CPPFLAGS = $(bitcoin_bin_cppflags)
697705
bitcoin_wallet_CXXFLAGS = $(bitcoin_bin_cxxflags)
698706
bitcoin_wallet_LDFLAGS = $(bitcoin_bin_ldflags)
699-
bitcoin_wallet_LDADD = $(LIBBITCOIN_WALLET_TOOL) $(bitcoin_bin_ldadd)
707+
bitcoin_wallet_LDADD = $(LIBBITCOIN_WALLET_TOOL) $(bitcoin_bin_ldadd) $(LIBBITCOIN_IPC) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UTIL) $(LIBMULTIPROCESS_LIBS)
700708

701709
if TARGET_WINDOWS
702710
bitcoin_wallet_SOURCES += bitcoin-wallet-res.rc
@@ -814,17 +822,38 @@ if HARDEN
814822
endif
815823

816824
libbitcoin_ipc_mpgen_input = \
825+
ipc/capnp/chain.capnp \
826+
ipc/capnp/common.capnp \
817827
ipc/capnp/echo.capnp \
818-
ipc/capnp/init.capnp
828+
ipc/capnp/handler.capnp \
829+
ipc/capnp/init.capnp \
830+
ipc/capnp/node.capnp \
831+
ipc/capnp/wallet.capnp
819832
EXTRA_DIST += $(libbitcoin_ipc_mpgen_input)
820833
%.capnp:
821834

822835
if BUILD_MULTIPROCESS
823836
LIBBITCOIN_IPC=libbitcoin_ipc.a
824837
libbitcoin_ipc_a_SOURCES = \
838+
ipc/capnp/chain-types.h \
839+
ipc/capnp/chain.cpp \
840+
ipc/capnp/common-types.h \
841+
ipc/capnp/common.cpp \
842+
ipc/capnp/common.h \
843+
ipc/capnp/context.h \
844+
ipc/capnp/handler.cpp \
825845
ipc/capnp/init-types.h \
846+
ipc/capnp/init.cpp \
847+
ipc/capnp/node-types.h \
848+
ipc/capnp/node.cpp \
849+
ipc/capnp/node.h \
826850
ipc/capnp/protocol.cpp \
827851
ipc/capnp/protocol.h \
852+
ipc/capnp/wallet-types.h \
853+
ipc/capnp/wallet.cpp \
854+
ipc/capnp/wallet.h \
855+
ipc/context.cpp \
856+
ipc/context.h \
828857
ipc/exception.h \
829858
ipc/interfaces.cpp \
830859
ipc/process.cpp \

src/Makefile.qt.include

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,15 +332,15 @@ bitcoin_qt_libtoolflags = $(AM_LIBTOOLFLAGS) --tag CXX
332332

333333
qt_bitcoin_qt_CPPFLAGS = $(bitcoin_qt_cppflags)
334334
qt_bitcoin_qt_CXXFLAGS = $(bitcoin_qt_cxxflags)
335-
qt_bitcoin_qt_SOURCES = $(bitcoin_qt_sources)
335+
qt_bitcoin_qt_SOURCES = $(bitcoin_qt_sources) init/bitcoin-qt.cpp
336336
qt_bitcoin_qt_LDADD = $(bitcoin_qt_ldadd)
337337
qt_bitcoin_qt_LDFLAGS = $(bitcoin_qt_ldflags)
338338
qt_bitcoin_qt_LIBTOOLFLAGS = $(bitcoin_qt_libtoolflags)
339339

340340
bitcoin_gui_CPPFLAGS = $(bitcoin_qt_cppflags)
341341
bitcoin_gui_CXXFLAGS = $(bitcoin_qt_cxxflags)
342-
bitcoin_gui_SOURCES = $(bitcoin_qt_sources)
343-
bitcoin_gui_LDADD = $(bitcoin_qt_ldadd)
342+
bitcoin_gui_SOURCES = $(bitcoin_qt_sources) init/bitcoin-gui.cpp
343+
bitcoin_gui_LDADD = $(bitcoin_qt_ldadd) $(LIBBITCOIN_IPC) $(LIBBITCOIN_UTIL) $(LIBMULTIPROCESS_LIBS)
344344
bitcoin_gui_LDFLAGS = $(bitcoin_qt_ldflags)
345345
bitcoin_gui_LIBTOOLFLAGS = $(bitcoin_qt_libtoolflags)
346346

src/Makefile.qttest.include

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ qt_test_test_bitcoin_qt_SOURCES = \
3636
qt/test/test_main.cpp \
3737
qt/test/uritests.cpp \
3838
qt/test/util.cpp \
39-
$(TEST_QT_H)
39+
$(TEST_QT_H) \
40+
init/bitcoin-qt.cpp
4041
if ENABLE_WALLET
4142
qt_test_test_bitcoin_qt_SOURCES += \
4243
qt/test/addressbooktests.cpp \

src/bitcoin-wallet.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <chainparams.h>
1010
#include <chainparamsbase.h>
11+
#include <interfaces/init.h>
1112
#include <logging.h>
1213
#include <util/system.h>
1314
#include <util/translation.h>
@@ -17,7 +18,7 @@
1718
#include <functional>
1819

1920
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
20-
UrlDecodeFn* const URL_DECODE = nullptr;
21+
UrlDecodeFn* const URL_DECODE = urlDecode;
2122

2223
static void SetupWalletToolArgs(ArgsManager& argsman)
2324
{
@@ -83,6 +84,13 @@ int main(int argc, char* argv[])
8384
util::WinCmdLineArgs winArgs;
8485
std::tie(argc, argv) = winArgs.get();
8586
#endif
87+
88+
int exit_status;
89+
std::unique_ptr<interfaces::Init> init = interfaces::MakeWalletInit(argc, argv, exit_status);
90+
if (!init) {
91+
return exit_status;
92+
}
93+
8694
SetupEnvironment();
8795
RandomInit();
8896
try {

src/bitcoind.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ static bool AppInit(NodeContext& node, int argc, char* argv[])
111111
util::ThreadSetInternalName("init");
112112

113113
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
114-
SetupServerArgs(node);
115114
ArgsManager& args = *Assert(node.args);
115+
SetupServerArgs(args);
116116
std::string error;
117117
if (!args.ParseParameters(argc, argv, error)) {
118118
return InitError(Untranslated(strprintf("Error parsing command line arguments: %s\n", error)));

0 commit comments

Comments
 (0)