Skip to content

Commit

Permalink
ipc-connect # Add bitcoin-gui -ipcconnect option
Browse files Browse the repository at this point in the history
Add bitcoin-gui -ipcconnect option

Add `-ipcconnect` option to `bitcoin-gui` to allow connecting gui to an
existing node instead of starting a new node process, so it is possible to
start and stop the gui independently of the node.

This change doesn't add an -ipcbind option to the bitcoin-wallet (which would
allow the gui to control wallet processes without going through the node), but
this would be a logical extension to add in the future.
  • Loading branch information
ryanofsky committed Mar 6, 2020
1 parent c83e46c commit 1a1c4e0
Show file tree
Hide file tree
Showing 23 changed files with 233 additions and 257 deletions.
1 change: 1 addition & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ void SetupServerArgs(interfaces::LocalInit& init)

if (init.m_protocol) {
gArgs.AddArg("-ipcbind=<address>", "Bind bitcoin-node process to tcp or unix socket address.", ArgsManager::ALLOW_ANY, OptionsCategory::IPC);
gArgs.AddArg("-ipcconnect=<address>", "Instead of starting a bitcoin-node process in the background, connect to the an existing process listening at the specified address. Valid address values are 'unix<socket path>' to connect to '<datadir>/node.sock' socket, or 'unix:<socket path>' to connect to a different socket path.", ArgsManager::ALLOW_ANY, OptionsCategory::IPC);
}

#if HAVE_DECL_DAEMON
Expand Down
122 changes: 58 additions & 64 deletions src/interfaces/capnp/node.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -15,70 +15,64 @@ using Handler = import "handler.capnp";
interface Node $Proxy.wrap("interfaces::Node") {
destroy @0 (context :Proxy.Context) -> ();
initError @1 (context :Proxy.Context, message :Text) -> ();
customSetupServerArgs @2 (context :Proxy.Context) -> () $Proxy.name("setupServerArgs");
customParseParameters @3 (context :Proxy.Context, argv :List(Text) $Proxy.count(2)) -> (errorStr :Text, result :Bool) $Proxy.name("parseParameters");
customForceSetArg @4 (context :Proxy.Context, arg :Text, value :Text) -> () $Proxy.name("forceSetArg");
customSoftSetArg @5 (context :Proxy.Context, arg :Text, value :Text) -> (result :Bool) $Proxy.name("softSetArg");
customSoftSetBoolArg @6 (context :Proxy.Context, arg :Text, value :Bool) -> (result :Bool) $Proxy.name("softSetBoolArg");
customReadConfigFiles @7 (context :Proxy.Context) -> (errorStr :Text, result: Bool) $Proxy.name("readConfigFiles");
customSelectParams @8 (context :Proxy.Context, network :Text) -> (error :Text $Proxy.exception("std::exception")) $Proxy.name("selectParams");
customBaseInitialize @9 (context :Proxy.Context) -> (error :Text $Proxy.exception("std::exception"), result :Bool) $Proxy.name("baseInitialize");
getAssumedBlockchainSize @10 (context :Proxy.Context) -> (result :UInt64);
getAssumedChainStateSize @11 (context :Proxy.Context) -> (result :UInt64);
getNetwork @12 (context :Proxy.Context) -> (result :Text);
initLogging @13 (context :Proxy.Context) -> ();
initParameterInteraction @14 (context :Proxy.Context) -> ();
getWarnings @15 (context :Proxy.Context) -> (result :Text);
getLogCategories @16 (context :Proxy.Context) -> (result :UInt32);
appInitMain @17 (context :Proxy.Context) -> (error :Text $Proxy.exception("std::exception"), result :Bool);
appShutdown @18 (context :Proxy.Context) -> ();
startShutdown @19 (context :Proxy.Context) -> ();
shutdownRequested @20 (context :Proxy.Context) -> (result :Bool);
mapPort @21 (context :Proxy.Context, useUPnP :Bool) -> ();
getProxy @22 (context :Proxy.Context, net :Int32) -> (proxyInfo :ProxyType, result :Bool);
getNodeCount @23 (context :Proxy.Context, flags :Int32) -> (result :UInt64);
getNodesStats @24 (context :Proxy.Context) -> (stats :List(NodeStats), result :Bool);
getBanned @25 (context :Proxy.Context) -> (banmap :List(Common.Pair(Data, Data)), result :Bool);
ban @26 (context :Proxy.Context, netAddr :Data, reason :Int32, banTimeOffset :Int64) -> (result :Bool);
unban @27 (context :Proxy.Context, ip :Data) -> (result :Bool);
disconnectByAddress @28 (context :Proxy.Context, address :Data) -> (result :Bool);
disconnectById @29 (context :Proxy.Context, id :Int64) -> (result :Bool);
getTotalBytesRecv @30 (context :Proxy.Context) -> (result :Int64);
getTotalBytesSent @31 (context :Proxy.Context) -> (result :Int64);
getMempoolSize @32 (context :Proxy.Context) -> (result :UInt64);
getMempoolDynamicUsage @33 (context :Proxy.Context) -> (result :UInt64);
getHeaderTip @34 (context :Proxy.Context) -> (height :Int32, blockTime :Int64, result :Bool);
getNumBlocks @35 (context :Proxy.Context) -> (result :Int32);
getLastBlockTime @36 (context :Proxy.Context) -> (result :Int64);
getVerificationProgress @37 (context :Proxy.Context) -> (result :Float64);
isInitialBlockDownload @38 (context :Proxy.Context) -> (result :Bool);
getReindex @39 (context :Proxy.Context) -> (result :Bool);
getImporting @40 (context :Proxy.Context) -> (result :Bool);
setNetworkActive @41 (context :Proxy.Context, active :Bool) -> ();
getNetworkActive @42 (context :Proxy.Context) -> (result :Bool);
estimateSmartFee @43 (context :Proxy.Context, numBlocks :Int32, conservative :Bool, wantReturnedTarget :Bool) -> (returnedTarget :Int32, result :Data);
getDustRelayFee @44 (context :Proxy.Context) -> (result :Data);
executeRpc @45 (context :Proxy.Context, command :Text, params :Common.UniValue, uri :Text) -> (error :Text $Proxy.exception("std::exception"), rpcError :Common.UniValue $Proxy.exception("UniValue"), result :Common.UniValue);
listRpcCommands @46 (context :Proxy.Context) -> (result :List(Text));
rpcSetTimerInterfaceIfUnset @47 (context :Proxy.Context, iface :Void) -> ();
rpcUnsetTimerInterface @48 (context :Proxy.Context, iface :Void) -> ();
getUnspentOutput @49 (context :Proxy.Context, output :Data) -> (coin :Data, result :Bool);
getWalletDir @50 (context :Proxy.Context) -> (result :Text);
listWalletDir @51 (context :Proxy.Context) -> (result :List(Text));
getWallets @52 (context :Proxy.Context) -> (result :List(Wallet.Wallet));
loadWallet @53 (context :Proxy.Context, name :Text) -> (error :Text, warning :List(Text), result :Wallet.Wallet);
createWallet @54 (context :Proxy.Context, passphrase :Text, flags :UInt64, name :Text) -> (error :Text, warning :List(Text), status: Int32, result :Wallet.Wallet);
handleInitMessage @55 (context :Proxy.Context, callback :InitMessageCallback) -> (result :Handler.Handler);
handleMessageBox @56 (context :Proxy.Context, callback :MessageBoxCallback) -> (result :Handler.Handler);
handleQuestion @57 (context :Proxy.Context, callback :QuestionCallback) -> (result :Handler.Handler);
handleShowProgress @58 (context :Proxy.Context, callback :ShowNodeProgressCallback) -> (result :Handler.Handler);
handleLoadWallet @59 (context :Proxy.Context, callback :LoadWalletCallback) -> (result :Handler.Handler);
handleNotifyNumConnectionsChanged @60 (context :Proxy.Context, callback :NotifyNumConnectionsChangedCallback) -> (result :Handler.Handler);
handleNotifyNetworkActiveChanged @61 (context :Proxy.Context, callback :NotifyNetworkActiveChangedCallback) -> (result :Handler.Handler);
handleNotifyAlertChanged @62 (context :Proxy.Context, callback :NotifyAlertChangedCallback) -> (result :Handler.Handler);
handleBannedListChanged @63 (context :Proxy.Context, callback :BannedListChangedCallback) -> (result :Handler.Handler);
handleNotifyBlockTip @64 (context :Proxy.Context, callback :NotifyBlockTipCallback) -> (result :Handler.Handler);
handleNotifyHeaderTip @65 (context :Proxy.Context, callback :NotifyHeaderTipCallback) -> (result :Handler.Handler);
getAssumedBlockchainSize @2 (context :Proxy.Context) -> (result :UInt64);
getAssumedChainStateSize @3 (context :Proxy.Context) -> (result :UInt64);
getNetwork @4 (context :Proxy.Context) -> (result :Text);
initLogging @5 (context :Proxy.Context) -> ();
initParameterInteraction @6 (context :Proxy.Context) -> ();
getWarnings @7 (context :Proxy.Context) -> (result :Text);
getLogCategories @8 (context :Proxy.Context) -> (result :UInt32);
baseInitialize @9 (context :Proxy.Context, globalArgs :Common.GlobalArgs) -> (error :Text $Proxy.exception("std::exception"), result :Bool);
appInitMain @10 (context :Proxy.Context) -> (error :Text $Proxy.exception("std::exception"), result :Bool);
appShutdown @11 (context :Proxy.Context) -> ();
startShutdown @12 (context :Proxy.Context) -> ();
shutdownRequested @13 (context :Proxy.Context) -> (result :Bool);
mapPort @14 (context :Proxy.Context, useUPnP :Bool) -> ();
getProxy @15 (context :Proxy.Context, net :Int32) -> (proxyInfo :ProxyType, result :Bool);
getNodeCount @16 (context :Proxy.Context, flags :Int32) -> (result :UInt64);
getNodesStats @17 (context :Proxy.Context) -> (stats :List(NodeStats), result :Bool);
getBanned @18 (context :Proxy.Context) -> (banmap :List(Common.Pair(Data, Data)), result :Bool);
ban @19 (context :Proxy.Context, netAddr :Data, reason :Int32, banTimeOffset :Int64) -> (result :Bool);
unban @20 (context :Proxy.Context, ip :Data) -> (result :Bool);
disconnectByAddress @21 (context :Proxy.Context, address :Data) -> (result :Bool);
disconnectById @22 (context :Proxy.Context, id :Int64) -> (result :Bool);
getTotalBytesRecv @23 (context :Proxy.Context) -> (result :Int64);
getTotalBytesSent @24 (context :Proxy.Context) -> (result :Int64);
getMempoolSize @25 (context :Proxy.Context) -> (result :UInt64);
getMempoolDynamicUsage @26 (context :Proxy.Context) -> (result :UInt64);
getHeaderTip @27 (context :Proxy.Context) -> (height :Int32, blockTime :Int64, result :Bool);
getNumBlocks @28 (context :Proxy.Context) -> (result :Int32);
getLastBlockTime @29 (context :Proxy.Context) -> (result :Int64);
getVerificationProgress @30 (context :Proxy.Context) -> (result :Float64);
isInitialBlockDownload @31 (context :Proxy.Context) -> (result :Bool);
getReindex @32 (context :Proxy.Context) -> (result :Bool);
getImporting @33 (context :Proxy.Context) -> (result :Bool);
setNetworkActive @34 (context :Proxy.Context, active :Bool) -> ();
getNetworkActive @35 (context :Proxy.Context) -> (result :Bool);
estimateSmartFee @36 (context :Proxy.Context, numBlocks :Int32, conservative :Bool, wantReturnedTarget :Bool) -> (returnedTarget :Int32, result :Data);
getDustRelayFee @37 (context :Proxy.Context) -> (result :Data);
executeRpc @38 (context :Proxy.Context, command :Text, params :Common.UniValue, uri :Text) -> (error :Text $Proxy.exception("std::exception"), rpcError :Common.UniValue $Proxy.exception("UniValue"), result :Common.UniValue);
listRpcCommands @39 (context :Proxy.Context) -> (result :List(Text));
rpcSetTimerInterfaceIfUnset @40 (context :Proxy.Context, iface :Void) -> ();
rpcUnsetTimerInterface @41 (context :Proxy.Context, iface :Void) -> ();
getUnspentOutput @42 (context :Proxy.Context, output :Data) -> (coin :Data, result :Bool);
getWalletDir @43 (context :Proxy.Context) -> (result :Text);
listWalletDir @44 (context :Proxy.Context) -> (result :List(Text));
getWallets @45 (context :Proxy.Context) -> (result :List(Wallet.Wallet));
loadWallet @46 (context :Proxy.Context, name :Text) -> (error :Text, warning :List(Text), result :Wallet.Wallet);
createWallet @47 (context :Proxy.Context, passphrase :Text, flags :UInt64, name :Text) -> (error :Text, warning :List(Text), status: Int32, result :Wallet.Wallet);
handleInitMessage @48 (context :Proxy.Context, callback :InitMessageCallback) -> (result :Handler.Handler);
handleMessageBox @49 (context :Proxy.Context, callback :MessageBoxCallback) -> (result :Handler.Handler);
handleQuestion @50 (context :Proxy.Context, callback :QuestionCallback) -> (result :Handler.Handler);
handleShowProgress @51 (context :Proxy.Context, callback :ShowNodeProgressCallback) -> (result :Handler.Handler);
handleLoadWallet @52 (context :Proxy.Context, callback :LoadWalletCallback) -> (result :Handler.Handler);
handleNotifyNumConnectionsChanged @53 (context :Proxy.Context, callback :NotifyNumConnectionsChangedCallback) -> (result :Handler.Handler);
handleNotifyNetworkActiveChanged @54 (context :Proxy.Context, callback :NotifyNetworkActiveChangedCallback) -> (result :Handler.Handler);
handleNotifyAlertChanged @55 (context :Proxy.Context, callback :NotifyAlertChangedCallback) -> (result :Handler.Handler);
handleBannedListChanged @56 (context :Proxy.Context, callback :BannedListChangedCallback) -> (result :Handler.Handler);
handleNotifyBlockTip @57 (context :Proxy.Context, callback :NotifyBlockTipCallback) -> (result :Handler.Handler);
handleNotifyHeaderTip @58 (context :Proxy.Context, callback :NotifyHeaderTipCallback) -> (result :Handler.Handler);
getArg @59 (context :Proxy.Context, arg :Text, defaultValue: Text) -> (result :Text);
}

interface InitMessageCallback $Proxy.wrap("ProxyCallback<interfaces::Node::InitMessageFn>") {
Expand Down
55 changes: 0 additions & 55 deletions src/interfaces/capnp/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,61 +89,6 @@ void ProxyServerMethodTraits<interfaces::capnp::messages::Node::RpcUnsetTimerInt
context.proxy_server.m_timer_interface.reset();
}

void ProxyClientCustom<interfaces::capnp::messages::Node, interfaces::Node>::setupServerArgs()
{
interfaces::LocalInit& init = *static_cast<interfaces::LocalInit*>(m_connection->m_loop.m_context);
SetupServerArgs(init);
self().customSetupServerArgs();
}

bool ProxyClientCustom<interfaces::capnp::messages::Node, interfaces::Node>::parseParameters(int argc,
const char* const argv[],
std::string& error)
{
return gArgs.ParseParameters(argc, argv, error) & self().customParseParameters(argc, argv, error);
}

void ProxyClientCustom<interfaces::capnp::messages::Node, interfaces::Node>::forceSetArg(const std::string& arg,
const std::string& value)
{
gArgs.ForceSetArg(arg, value);
self().customForceSetArg(arg, value);
}

bool ProxyClientCustom<interfaces::capnp::messages::Node, interfaces::Node>::softSetArg(const std::string& arg,
const std::string& value)
{
gArgs.SoftSetArg(arg, value);
return self().customSoftSetArg(arg, value);
}

bool ProxyClientCustom<interfaces::capnp::messages::Node, interfaces::Node>::softSetBoolArg(const std::string& arg,
bool value)
{
gArgs.SoftSetBoolArg(arg, value);
return self().customSoftSetBoolArg(arg, value);
}

bool ProxyClientCustom<interfaces::capnp::messages::Node, interfaces::Node>::readConfigFiles(std::string& error)
{
return gArgs.ReadConfigFiles(error) & self().customReadConfigFiles(error);
}

void ProxyClientCustom<interfaces::capnp::messages::Node, interfaces::Node>::selectParams(const std::string& network)
{
SelectParams(network);
self().customSelectParams(network);
}

bool ProxyClientCustom<interfaces::capnp::messages::Node, interfaces::Node>::baseInitialize()
{
// TODO in future PR: Refactor bitcoin startup code, dedup this with AppInit.
SelectParams(interfaces::capnp::GlobalArgsNetwork());
InitLogging();
InitParameterInteraction();
return self().customBaseInitialize();
}

void CustomReadMessage(InvokeContext& invoke_context,
interfaces::capnp::messages::NodeStats::Reader const& reader,
std::tuple<CNodeStats, bool, CNodeStateStats>& node_stats)
Expand Down
21 changes: 0 additions & 21 deletions src/interfaces/capnp/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,6 @@

class RPCTimerInterface;

//! Specialization of Node client to deal with argument & config handling across
//! processes. If node and node client are running in same process it's
//! sufficient to only call parseParameters, softSetArgs, etc methods only on the
//! node object, but if node is running in a different process, the calls need to
//! be made repeated locally as well to update the state of the client process..
template <>
class mp::ProxyClientCustom<interfaces::capnp::messages::Node, interfaces::Node>
: public mp::ProxyClientBase<interfaces::capnp::messages::Node, interfaces::Node>
{
public:
using ProxyClientBase::ProxyClientBase;
void setupServerArgs() override;
bool parseParameters(int argc, const char* const argv[], std::string& error) override;
void forceSetArg(const std::string& arg, const std::string& value) override;
bool softSetArg(const std::string& arg, const std::string& value) override;
bool softSetBoolArg(const std::string& arg, bool value) override;
bool readConfigFiles(std::string& error) override;
void selectParams(const std::string& network) override;
bool baseInitialize() override;
};

//! Specialization of Node proxy server needed to add m_timer_interface
//! member used by rpcSetTimerInterfaceIfUnset and rpcUnsetTimerInterface
//! methods.
Expand Down
11 changes: 11 additions & 0 deletions src/interfaces/init_bitcoin-node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
#include <interfaces/init.h>

#include <chainparams.h>
#include <init.h>
#include <interfaces/capnp/ipc.h>
#include <interfaces/chain.h>
#include <interfaces/node.h>
#include <node/context.h>

namespace interfaces {
void MakeProxy(NodeServerParam&);
namespace capnp {
std::string GlobalArgsNetwork();
} // namespace capnp
namespace {
class LocalInitImpl : public LocalInit
{
Expand All @@ -32,6 +36,13 @@ class LocalInitImpl : public LocalInit
});
return wallet;
}
void initProcess() override
{
// TODO in future PR: Refactor bitcoin startup code, dedup this with AppInit.
SelectParams(interfaces::capnp::GlobalArgsNetwork());
InitLogging();
InitParameterInteraction();
}
void makeNodeServer(NodeServerParam& param) override { MakeProxy(param); }
NodeContext& node() override { return m_node; };
NodeContext m_node;
Expand Down
14 changes: 4 additions & 10 deletions src/interfaces/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,13 @@ class NodeImpl : public Node
public:
explicit NodeImpl(LocalInit& init) : m_init(init) {}
void initError(const std::string& message) override { InitError(message); }
bool parseParameters(int argc, const char* const argv[], std::string& error) override
{
return gArgs.ParseParameters(argc, argv, error);
}
bool readConfigFiles(std::string& error) override { return gArgs.ReadConfigFiles(error, true); }
void forceSetArg(const std::string& arg, const std::string& value) override { gArgs.ForceSetArg(arg, value); }
bool softSetArg(const std::string& arg, const std::string& value) override { return gArgs.SoftSetArg(arg, value); }
bool softSetBoolArg(const std::string& arg, bool value) override { return gArgs.SoftSetBoolArg(arg, value); }
void selectParams(const std::string& network) override { SelectParams(network); }
uint64_t getAssumedBlockchainSize() override { return Params().AssumedBlockchainSize(); }
uint64_t getAssumedChainStateSize() override { return Params().AssumedChainStateSize(); }
std::string getNetwork() override { return Params().NetworkIDString(); }
std::string getArg(const std::string& arg, const std::string& default_value) override
{
return gArgs.GetArg(arg, default_value);
}
void initLogging() override { InitLogging(); }
void initParameterInteraction() override { InitParameterInteraction(); }
std::string getWarnings() override { return GetWarnings(true); }
Expand Down Expand Up @@ -106,7 +101,6 @@ class NodeImpl : public Node
StopMapPort();
}
}
void setupServerArgs() override { return SetupServerArgs(m_init); }
bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); }
size_t getNodeCount(CConnman::NumConnections flags) override
{
Expand Down
Loading

0 comments on commit 1a1c4e0

Please sign in to comment.