Skip to content

Commit 0ca73bc

Browse files
committed
Add barebones IPC framework to bitcoin-qt and bitcoind
This adds some IPC functions and classes in src/ipc/ that let bitcoin-qt fork a bitcoind process and communicate with it over a socketpair. Only a handful of IPC calls are implemented, but this demonstrates a working framework supporting bidirectional IPC calls (requests from bitcoin-qt to bitcoind and notifications from bitcoind to bitcoin-qt). The IPC protocol used in this implementation is Cap'n Proto (https://capnproto.org/), but this could be swapped out for another protocol. Can'n Proto types and libraries are only accessed in ipc/server.cpp and ipc/client.cpp, and not in any headers or other parts of bitcoin code.
1 parent 29efc39 commit 0ca73bc

37 files changed

+1939
-128
lines changed

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,7 @@ AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
11111111
AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes])
11121112
AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes])
11131113

1114+
AC_DEFINE_UNQUOTED(BITCOIN_DAEMON_NAME, "$BITCOIN_DAEMON_NAME", [Base name of bitcoind executable])
11141115
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
11151116
AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])
11161117
AC_DEFINE(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION, [Build revision])

src/Makefile.am

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ BITCOIN_CORE_H = \
102102
httpserver.h \
103103
indirectmap.h \
104104
init.h \
105+
ipc/client.h \
106+
ipc/interfaces.h \
107+
ipc/messages.capnp.h \
108+
ipc/serialize.h \
109+
ipc/server.h \
110+
ipc/util.h \
105111
key.h \
106112
keystore.h \
107113
dbwrapper.h \
@@ -173,7 +179,7 @@ obj/build.h: FORCE
173179
libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
174180

175181
# server: shared between bitcoind and bitcoin-qt
176-
libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
182+
libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) $(CAPNP_RPC_CFLAGS)
177183
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
178184
libbitcoin_server_a_SOURCES = \
179185
addrman.cpp \
@@ -326,6 +332,13 @@ libbitcoin_util_a_SOURCES = \
326332
compat/glibc_sanity.cpp \
327333
compat/glibcxx_sanity.cpp \
328334
compat/strnlen.cpp \
335+
ipc/client.cpp \
336+
ipc/interfaces.cpp \
337+
ipc/messages.capnp \
338+
ipc/messages.capnp.c++ \
339+
ipc/serialize.cpp \
340+
ipc/server.cpp \
341+
ipc/util.cpp \
329342
random.cpp \
330343
rpc/protocol.cpp \
331344
support/cleanse.cpp \
@@ -374,7 +387,7 @@ bitcoind_LDADD = \
374387
$(LIBMEMENV) \
375388
$(LIBSECP256K1)
376389

377-
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
390+
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) $(CAPNP_RPC_LIBS)
378391

379392
# bitcoin-cli binary #
380393
bitcoin_cli_SOURCES = bitcoin-cli.cpp

src/Makefile.qt.include

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
409409
endif
410410
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
411411
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
412-
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
412+
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(CAPNP_RPC_LIBS)
413413
qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
414414
qt_bitcoin_qt_LIBTOOLFLAGS = --tag CXX
415415

src/Makefile.qttest.include

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ endif
6161
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \
6262
$(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
6363
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
64-
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
64+
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(CAPNP_RPC_LIBS)
6565
qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
6666
qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
6767

src/bitcoind.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "compat.h"
1313
#include "rpc/server.h"
1414
#include "init.h"
15+
#include "ipc/server.h"
1516
#include "noui.h"
1617
#include "scheduler.h"
1718
#include "util.h"
@@ -188,6 +189,13 @@ bool AppInit(int argc, char* argv[])
188189

189190
int main(int argc, char* argv[])
190191
{
192+
// Check if bitcoind is being invoked as an IPC server. If so, then bypass
193+
// normal execution and just respond to requests from the IPC channel.
194+
int exitStatus;
195+
if (ipc::StartServer(argc, argv, exitStatus)) {
196+
return exitStatus;
197+
}
198+
191199
SetupEnvironment();
192200

193201
// Connect bitcoind signal handlers

src/ipc/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
Bitcoin Interprocess Communication
2+
==================================
3+
4+
The IPC functions and classes in `src/ipc/` allow the `bitcoin-qt` process to
5+
fork a `bitcoind` process and communicate with it over a socketpair. This gives
6+
`bitcoin-qt` a code a bit of modularity, avoiding a monolithic architecture
7+
where UI, P2P, wallet, consensus, and database code all runs in a single
8+
process.
9+
10+
In the future, the IPC mechanism could be extended to allow other subdivisions
11+
of functionality. For example, wallet code could run in a separate process from
12+
P2P code. Also in the future, IPC sockets could also be exposed more publicly.
13+
For example, exposed IPC server sockets could allow a `bitcoin-qt` process to
14+
control a `bitcoind` process other than the one it spawns internally. These
15+
changes would be straightforward to implement, but would create security,
16+
backwards-compatibility, complexity, and maintainablity concerns, so would
17+
require further discussion.
18+
19+
The IPC protocol used is [Cap'n Proto](https://capnproto.org/), but the protocol
20+
could be swapped out for another protocol (such as JSON-RPC with long polling)
21+
without changing any code outside of the `src/ipc/` directory. No Cap'n Proto
22+
types are used or headers included in any public interface.
23+
24+
Here are the important files in the `src/ipc/` directory:
25+
26+
Public Interfaces
27+
-----------------
28+
29+
* `interfaces.h``Node`, `Wallet`, `Handler` interface definitions
30+
31+
* `client.h``StartClient` function to spawn a `bitcoind` process and
32+
return a `Node` object controlling it through a socketpair.
33+
34+
* `server.h``StartServer` function to allow a `bitcoind` process to
35+
open a socket file descriptor and respond to remote commands.
36+
37+
Other Files
38+
-----------
39+
40+
* `interfaces.cpp – In-process implementations of `Node`, `Wallet`, `Handler`
41+
interfaces.
42+
43+
* `client.cpp – IPC implementations of `Node`, `Wallet`, `Handler`
44+
interfaces that forward calls to a socket.
45+
46+
* `server.cpp – IPC implementation responding to client requests.
47+
48+
* `messages.capnp – IPC interface definition.
49+
50+
* `serialize.{h,cpp}` – Helper functions for translating IPC messages.
51+
52+
* `util.{h,cpp}` – Helper functions for making and receiving IPC calls.

0 commit comments

Comments
 (0)