Skip to content

Commit

Permalink
multiprocess: Add bitcoin-wallet -ipcconnect option
Browse files Browse the repository at this point in the history
Add `-ipcconnect` option to `bitcoin-wallet` to allow connecting to a bitcoin
node process over IPC.  The `bitcoin-wallet` tool doesn't really do anything with its
connection to the node yet, but it could potentially run or serve RPCs that
require being online.

Example usage:

    src/bitcoin-node -regtest -debug -ipcbind=unix
    src/bitcoin-wallet -regtest -ipcconnect=unix info
  • Loading branch information
ryanofsky committed Jul 26, 2024
1 parent dc68dcd commit 7c4af4b
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 10 deletions.
22 changes: 19 additions & 3 deletions src/bitcoin-wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
#include <common/args.h>
#include <common/system.h>
#include <compat/compat.h>
#include <interfaces/chain.h>
#include <interfaces/init.h>
#include <interfaces/ipc.h>
#include <key.h>
#include <logging.h>
#include <pubkey.h>
Expand All @@ -28,7 +30,7 @@ using util::Join;

const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;

static void SetupWalletToolArgs(ArgsManager& argsman)
static void SetupWalletToolArgs(ArgsManager& argsman, bool can_connect_ipc)
{
SetupHelpOptions(argsman);
SetupChainParamsBaseOptions(argsman);
Expand All @@ -43,6 +45,9 @@ static void SetupWalletToolArgs(ArgsManager& argsman)
argsman.AddArg("-format=<format>", "The format of the wallet file to create. Either \"bdb\" or \"sqlite\". Only used with 'createfromdump'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-withinternalbdb", "Use the internal Berkeley DB parser when dumping a Berkeley DB wallet file (default: false)", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
if (can_connect_ipc) {
argsman.AddArg("-ipcconnect=<address>", "Connect to bitcoin-node process in the background to perform online operations. Valid <address> values are 'auto' to try connecting to default socket in <datadir>/sockets/node.sock, but proceed offline if it isn't available, 'unix' to connect to the default socket and fail if it isn't available, 'unix:<socket path>' to connect to a socket at a nonstandard path, and -noipcconnect to not connect. Default value: auto", ArgsManager::ALLOW_ANY, OptionsCategory::IPC);
}

argsman.AddCommand("info", "Get wallet info");
argsman.AddCommand("create", "Create new wallet file");
Expand All @@ -53,7 +58,6 @@ static void SetupWalletToolArgs(ArgsManager& argsman)

static std::optional<int> WalletAppInit(ArgsManager& args, int argc, char* argv[])
{
SetupWalletToolArgs(args);
std::string error_message;
if (!args.ParseParameters(argc, argv, error_message)) {
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error_message);
Expand Down Expand Up @@ -112,6 +116,7 @@ MAIN_FUNCTION
SetupEnvironment();
RandomInit();
try {
SetupWalletToolArgs(args, init->canConnectIpc());
if (const auto maybe_exit{WalletAppInit(args, argc, argv)}) return *maybe_exit;
} catch (const std::exception& e) {
PrintExceptionContinue(&e, "WalletAppInit()");
Expand All @@ -132,7 +137,18 @@ MAIN_FUNCTION
}

ECC_Context ecc_context{};
if (!wallet::WalletTool::ExecuteWalletToolFunc(args, command->command)) {

std::unique_ptr<interfaces::Chain> chain;
if (interfaces::Ipc* ipc = init->ipc()) {
std::string address = args.GetArg("-ipcconnect", "auto");
if (auto init = ipc->connectAddress(address)) {
tfm::format(std::cout, "Connected to IPC address %s\n", address);
chain = init->makeChain();
ipc->addCleanup(*chain, [init = init.release()] { delete init; });
}
}

if (!wallet::WalletTool::ExecuteWalletToolFunc(args, chain.get(), command->command)) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
Expand Down
1 change: 1 addition & 0 deletions src/init/bitcoin-wallet-ipc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class BitcoinWalletInit : public interfaces::Init
return MakeWalletLoader(chain, gArgs);
}
interfaces::Ipc* ipc() override { return m_ipc.get(); }
bool canConnectIpc() override { return true; }
std::unique_ptr<interfaces::Ipc> m_ipc;
std::optional<kernel::Context> m_kernel;
std::optional<ECC_Context> m_ecc_context;
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Init
virtual std::unique_ptr<WalletLoader> makeWalletLoader(Chain& chain) { return nullptr; }
virtual std::unique_ptr<Echo> makeEcho() { return nullptr; }
virtual Ipc* ipc() { return nullptr; }
virtual bool canConnectIpc() { return false; }
virtual bool canListenIpc() { return false; }
};

Expand Down
11 changes: 5 additions & 6 deletions src/wallet/wallettool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flag
wallet_instance->TopUpKeyPool();
}

static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, DatabaseOptions options)
static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, DatabaseOptions options, interfaces::Chain* chain)
{
DatabaseStatus status;
bilingual_str error;
Expand All @@ -55,8 +55,7 @@ static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::pa
return nullptr;
}

// dummy chain interface
std::shared_ptr<CWallet> wallet_instance{new CWallet(/*chain=*/nullptr, name, std::move(database)), WalletToolReleaseWallet};
std::shared_ptr<CWallet> wallet_instance{new CWallet(chain, name, std::move(database)), WalletToolReleaseWallet};
DBErrors load_wallet_ret;
try {
load_wallet_ret = wallet_instance->LoadWallet();
Expand Down Expand Up @@ -110,7 +109,7 @@ static void WalletShowInfo(CWallet* wallet_instance)
tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
}

bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
bool ExecuteWalletToolFunc(const ArgsManager& args, interfaces::Chain* chain, const std::string& command)
{
if (args.IsArgSet("-format") && command != "createfromdump") {
tfm::format(std::cerr, "The -format option can only be used with the \"createfromdump\" command.\n");
Expand Down Expand Up @@ -156,7 +155,7 @@ bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
options.require_format = DatabaseFormat::SQLITE;
}

const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options, chain);
if (wallet_instance) {
WalletShowInfo(wallet_instance.get());
wallet_instance->Close();
Expand All @@ -165,7 +164,7 @@ bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
DatabaseOptions options;
ReadDatabaseArgs(args, options);
options.require_existing = true;
const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options, chain);
if (!wallet_instance) return false;
WalletShowInfo(wallet_instance.get());
wallet_instance->Close();
Expand Down
6 changes: 5 additions & 1 deletion src/wallet/wallettool.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@

class ArgsManager;

namespace interfaces {
class Chain;
} // namespace interfaces

namespace wallet {
namespace WalletTool {

bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command);
bool ExecuteWalletToolFunc(const ArgsManager& args, interfaces::Chain* chain, const std::string& command);

} // namespace WalletTool
} // namespace wallet
Expand Down

0 comments on commit 7c4af4b

Please sign in to comment.