Skip to content

Commit 30073e6

Browse files
committedSep 6, 2024
multiprocess: Add -ipcbind option to bitcoin-node
Add `-ipcbind` option to `bitcoin-node` to listen on an IPC socket and accept connections from other processes. In the future, there will be an `-ipcconnect` option added to `bitcoin-wallet` and `bitcoin-node` to allow wallet and gui processes to connect to the node and access it. Example usage: src/bitcoin-node -regtest -debug -ipcbind=unix src/bitcoin-wallet -regtest -ipcconnect=unix info src/bitcoin-gui -regtest -ipcconnect=unix src/bitcoin-mine -regtest -ipcconnect=unix
1 parent 73fe7d7 commit 30073e6

File tree

10 files changed

+34
-7
lines changed

10 files changed

+34
-7
lines changed
 

‎src/bitcoind.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,11 @@ int fork_daemon(bool nochdir, bool noclose, TokenPipeEnd& endpoint)
109109

110110
#endif
111111

112-
static bool ParseArgs(ArgsManager& args, int argc, char* argv[])
112+
static bool ParseArgs(NodeContext& node, int argc, char* argv[])
113113
{
114+
ArgsManager& args{*Assert(node.args)};
114115
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
115-
SetupServerArgs(args);
116+
SetupServerArgs(args, node.init->canListenIpc());
116117
std::string error;
117118
if (!args.ParseParameters(argc, argv, error)) {
118119
return InitError(Untranslated(strprintf("Error parsing command line arguments: %s", error)));
@@ -268,7 +269,7 @@ MAIN_FUNCTION
268269

269270
// Interpret command line arguments
270271
ArgsManager& args = *Assert(node.args);
271-
if (!ParseArgs(args, argc, argv)) return EXIT_FAILURE;
272+
if (!ParseArgs(node, argc, argv)) return EXIT_FAILURE;
272273
// Process early info return commands such as -help or -version
273274
if (ProcessInitCommands(args)) return EXIT_SUCCESS;
274275

‎src/common/args.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,9 @@ std::string ArgsManager::GetHelpMessage() const
635635
case OptionsCategory::RPC:
636636
usage += HelpMessageGroup("RPC server options:");
637637
break;
638+
case OptionsCategory::IPC:
639+
usage += HelpMessageGroup("IPC interprocess connection options:");
640+
break;
638641
case OptionsCategory::WALLET:
639642
usage += HelpMessageGroup("Wallet options:");
640643
break;

‎src/common/args.h

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ enum class OptionsCategory {
6464
COMMANDS,
6565
REGISTER_COMMANDS,
6666
CLI_COMMANDS,
67+
IPC,
6768

6869
HIDDEN // Always the last option to avoid printing these in the help
6970
};

‎src/init.cpp

+16-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <init/common.h>
3030
#include <interfaces/chain.h>
3131
#include <interfaces/init.h>
32+
#include <interfaces/ipc.h>
3233
#include <interfaces/mining.h>
3334
#include <interfaces/node.h>
3435
#include <kernel/context.h>
@@ -441,7 +442,7 @@ static void OnRPCStopped()
441442
LogDebug(BCLog::RPC, "RPC stopped.\n");
442443
}
443444

444-
void SetupServerArgs(ArgsManager& argsman)
445+
void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
445446
{
446447
SetupHelpOptions(argsman);
447448
argsman.AddArg("-help-debug", "Print help message with debugging options and exit", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); // server-only for now
@@ -676,6 +677,9 @@ void SetupServerArgs(ArgsManager& argsman)
676677
argsman.AddArg("-rpcwhitelistdefault", "Sets default behavior for rpc whitelisting. Unless rpcwhitelistdefault is set to 0, if any -rpcwhitelist is set, the rpc server acts as if all rpc users are subject to empty-unless-otherwise-specified whitelists. If rpcwhitelistdefault is set to 1 and no -rpcwhitelist is set, rpc server acts as if all rpc users are subject to empty whitelists.", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
677678
argsman.AddArg("-rpcworkqueue=<n>", strprintf("Set the depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
678679
argsman.AddArg("-server", "Accept command line and JSON-RPC commands", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
680+
if (can_listen_ipc) {
681+
argsman.AddArg("-ipcbind=<address>", "Bind to Unix socket address and listen for incoming connections. Valid address values are \"unix\" to listen on the default path, <datadir>/node.sock, or \"unix:/custom/path\" to specify a custom path. Can be specified multiple times to listen on multiple paths. Default behavior is not to listen on any path. If relative paths are specified, they are interpreted relative to the network data directory. If paths include any parent directory components and the parent directories do not exist, they will be created.", ArgsManager::ALLOW_ANY, OptionsCategory::IPC);
682+
}
679683

680684
#if HAVE_DECL_FORK
681685
argsman.AddArg("-daemon", strprintf("Run in the background as a daemon and accept commands (default: %d)", DEFAULT_DAEMON), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -1200,6 +1204,17 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
12001204
g_wallet_init_interface.Construct(node);
12011205
uiInterface.InitWallet();
12021206

1207+
if (interfaces::Ipc* ipc = node.init->ipc()) {
1208+
for (std::string address : gArgs.GetArgs("-ipcbind")) {
1209+
try {
1210+
ipc->listenAddress(address);
1211+
} catch (const std::exception& e) {
1212+
return InitError(strprintf(Untranslated("Unable to bind to IPC address '%s'. %s"), address, e.what()));
1213+
}
1214+
LogPrintf("Listening for IPC requests on address %s\n", address);
1215+
}
1216+
}
1217+
12031218
/* Register RPC commands regardless of -server setting so they will be
12041219
* available in the GUI RPC console even if external calls are disabled.
12051220
*/

‎src/init.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ bool AppInitMain(node::NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip
7474
/**
7575
* Register all arguments with the ArgsManager
7676
*/
77-
void SetupServerArgs(ArgsManager& argsman);
77+
void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc=false);
7878

7979
/** Validates requirements to run the indexes and spawns each index initial sync thread */
8080
bool StartIndexBackgroundSync(node::NodeContext& node);

‎src/init/bitcoin-gui.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ class BitcoinGuiInit : public interfaces::Init
3434
}
3535
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
3636
interfaces::Ipc* ipc() override { return m_ipc.get(); }
37+
// bitcoin-gui accepts -ipcbind option even though it does not use it
38+
// directly. It just returns true here to accept the option because
39+
// bitcoin-node accepts the option, and bitcoin-gui accepts all bitcoin-node
40+
// options and will start the node with those options.
41+
bool canListenIpc() override { return true; }
3742
node::NodeContext m_node;
3843
std::unique_ptr<interfaces::Ipc> m_ipc;
3944
};

‎src/init/bitcoin-node.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class BitcoinNodeInit : public interfaces::Init
3737
}
3838
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
3939
interfaces::Ipc* ipc() override { return m_ipc.get(); }
40+
bool canListenIpc() override { return true; }
4041
node::NodeContext& m_node;
4142
std::unique_ptr<interfaces::Ipc> m_ipc;
4243
};

‎src/interfaces/init.h

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Init
3737
virtual std::unique_ptr<WalletLoader> makeWalletLoader(Chain& chain) { return nullptr; }
3838
virtual std::unique_ptr<Echo> makeEcho() { return nullptr; }
3939
virtual Ipc* ipc() { return nullptr; }
40+
virtual bool canListenIpc() { return false; }
4041
};
4142

4243
//! Return implementation of Init interface for the node process. If the argv

‎src/qt/bitcoin.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ int GuiMain(int argc, char* argv[])
525525

526526
/// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
527527
// Command-line options take precedence:
528-
SetupServerArgs(gArgs);
528+
SetupServerArgs(gArgs, init->canListenIpc());
529529
SetupUIArgs(gArgs);
530530
std::string error;
531531
if (!gArgs.ParseParameters(argc, argv, error)) {

‎src/test/fuzz/system.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ FUZZ_TARGET(system, .init = initialize_system)
5959
args_manager.SoftSetBoolArg(str_arg, f_value);
6060
},
6161
[&] {
62-
const OptionsCategory options_category = fuzzed_data_provider.PickValueInArray<OptionsCategory>({OptionsCategory::OPTIONS, OptionsCategory::CONNECTION, OptionsCategory::WALLET, OptionsCategory::WALLET_DEBUG_TEST, OptionsCategory::ZMQ, OptionsCategory::DEBUG_TEST, OptionsCategory::CHAINPARAMS, OptionsCategory::NODE_RELAY, OptionsCategory::BLOCK_CREATION, OptionsCategory::RPC, OptionsCategory::GUI, OptionsCategory::COMMANDS, OptionsCategory::REGISTER_COMMANDS, OptionsCategory::CLI_COMMANDS, OptionsCategory::HIDDEN});
62+
const OptionsCategory options_category = fuzzed_data_provider.PickValueInArray<OptionsCategory>({OptionsCategory::OPTIONS, OptionsCategory::CONNECTION, OptionsCategory::WALLET, OptionsCategory::WALLET_DEBUG_TEST, OptionsCategory::ZMQ, OptionsCategory::DEBUG_TEST, OptionsCategory::CHAINPARAMS, OptionsCategory::NODE_RELAY, OptionsCategory::BLOCK_CREATION, OptionsCategory::RPC, OptionsCategory::GUI, OptionsCategory::COMMANDS, OptionsCategory::REGISTER_COMMANDS, OptionsCategory::CLI_COMMANDS, OptionsCategory::IPC, OptionsCategory::HIDDEN});
6363
// Avoid hitting:
6464
// common/args.cpp:563: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
6565
const std::string argument_name = GetArgumentName(fuzzed_data_provider.ConsumeRandomLengthString(16));

0 commit comments

Comments
 (0)
Please sign in to comment.