aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml1
-rw-r--r--doc/man/bitcoin-cli.12
-rw-r--r--doc/man/bitcoin-tx.12
-rw-r--r--doc/man/bitcoin-wallet.12
-rw-r--r--src/bench/bench_bitcoin.cpp7
-rw-r--r--src/bitcoin-cli.cpp7
-rw-r--r--src/bitcoin-tx.cpp7
-rw-r--r--src/bitcoin-wallet.cpp6
-rw-r--r--src/dummywallet.cpp9
-rw-r--r--src/init.cpp9
-rw-r--r--src/interfaces/node.cpp5
-rw-r--r--src/interfaces/node.h5
-rw-r--r--src/interfaces/wallet.cpp2
-rw-r--r--src/qt/bitcoin.cpp2
-rw-r--r--src/qt/bitcoingui.cpp37
-rw-r--r--src/qt/bitcoingui.h1
-rw-r--r--src/qt/walletcontroller.cpp49
-rw-r--r--src/qt/walletcontroller.h30
-rw-r--r--src/util/system.cpp6
-rw-r--r--src/util/system.h3
-rw-r--r--src/wallet/rpcwallet.cpp16
-rw-r--r--src/wallet/wallet.cpp22
-rw-r--r--src/wallet/wallet.h1
-rwxr-xr-xtest/functional/p2p_sendheaders.py2
-rwxr-xr-xtest/functional/test_runner.py4
25 files changed, 188 insertions, 49 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 08132edb7d..31c3aba8c6 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -17,6 +17,7 @@ install:
- cmd: pip install --quiet git+https://github.com/frerich/clcache.git@v4.2.0
# Disable zmq test for now since python zmq library on Windows would cause Access violation sometimes.
# - cmd: pip install zmq
+- cmd: vcpkg remove --outdated --recurse
- cmd: vcpkg install --triplet %PLATFORM%-windows-static %PACKAGES% > NUL
- cmd: del /s /q C:\Tools\vcpkg\installed\%PLATFORM%-windows-static\debug # Remove unused debug library
before_build:
diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1
index 355b4d3cc2..95c1d24dff 100644
--- a/doc/man/bitcoin-cli.1
+++ b/doc/man/bitcoin-cli.1
@@ -20,7 +20,7 @@ Bitcoin Core RPC client version v0.17.99.0
.HP
\-?
.IP
-This help message
+Print this help message and exit
.HP
\fB\-conf=\fR<file>
.IP
diff --git a/doc/man/bitcoin-tx.1 b/doc/man/bitcoin-tx.1
index c5d3985763..6b6071d9b7 100644
--- a/doc/man/bitcoin-tx.1
+++ b/doc/man/bitcoin-tx.1
@@ -14,7 +14,7 @@ Bitcoin Core bitcoin\-tx utility version v0.17.99.0
.HP
\-?
.IP
-This help message
+Print this help message and exit
.HP
\fB\-create\fR
.IP
diff --git a/doc/man/bitcoin-wallet.1 b/doc/man/bitcoin-wallet.1
index 3c4849cca7..1cb8cdebcd 100644
--- a/doc/man/bitcoin-wallet.1
+++ b/doc/man/bitcoin-wallet.1
@@ -15,7 +15,7 @@ bitcoin\-wallet [options] <command>
.HP
\-?
.IP
-This help message
+Print this help message and exit
.HP
\fB\-datadir=\fR<dir>
.IP
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index b804a84478..d67b2c5bc7 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -24,7 +24,8 @@ static const int64_t DEFAULT_PLOT_HEIGHT = 768;
static void SetupBenchArgs()
{
- gArgs.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
+ SetupHelpOptions(gArgs);
+
gArgs.AddArg("-list", "List benchmarks without executing them. Can be combined with -scaling and -filter", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-evals=<n>", strprintf("Number of measurement evaluations to perform. (default: %u)", DEFAULT_BENCH_EVALUATIONS), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-filter=<regex>", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), false, OptionsCategory::OPTIONS);
@@ -33,10 +34,6 @@ static void SetupBenchArgs()
gArgs.AddArg("-plot-plotlyurl=<uri>", strprintf("URL to use for plotly.js (default: %s)", DEFAULT_PLOT_PLOTLYURL), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-plot-width=<x>", strprintf("Plot width in pixel (default: %u)", DEFAULT_PLOT_WIDTH), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-plot-height=<x>", strprintf("Plot height in pixel (default: %u)", DEFAULT_PLOT_HEIGHT), false, OptionsCategory::OPTIONS);
-
- // Hidden
- gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
}
static fs::path SetDataDir()
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 7cdf61ad35..b0e1f67d93 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -34,11 +34,12 @@ static const int CONTINUE_EXECUTION=-1;
static void SetupCliArgs()
{
+ SetupHelpOptions(gArgs);
+
const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
- gArgs.AddArg("-?", "This help message", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-version", "Print version and exit", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS);
@@ -55,10 +56,6 @@ static void SetupCliArgs()
gArgs.AddArg("-rpcwallet=<walletname>", "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind). This changes the RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/<walletname>", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-stdin", "Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password.", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-stdinrpcpass", "Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password.", false, OptionsCategory::OPTIONS);
-
- // Hidden
- gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
}
/** libevent event log callback */
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 9d1309cde3..4be89aab6c 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -35,7 +35,8 @@ const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
static void SetupBitcoinTxArgs()
{
- gArgs.AddArg("-?", "This help message", false, OptionsCategory::OPTIONS);
+ SetupHelpOptions(gArgs);
+
gArgs.AddArg("-create", "Create new, empty TX.", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-json", "Select JSON output", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-txid", "Output only the hex-encoded transaction id of the resultant transaction.", false, OptionsCategory::OPTIONS);
@@ -66,10 +67,6 @@ static void SetupBitcoinTxArgs()
gArgs.AddArg("load=NAME:FILENAME", "Load JSON file FILENAME into register NAME", false, OptionsCategory::REGISTER_COMMANDS);
gArgs.AddArg("set=NAME:JSON-STRING", "Set register NAME to given JSON-STRING", false, OptionsCategory::REGISTER_COMMANDS);
-
- // Hidden
- gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
}
//
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index 11caa0dc6c..32a539aac6 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -20,9 +20,9 @@ const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
static void SetupWalletToolArgs()
{
+ SetupHelpOptions(gArgs);
SetupChainParamsBaseOptions();
- gArgs.AddArg("-?", "This help message", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-wallet=<wallet-name>", "Specify wallet name", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-debug=<category>", "Output debugging information (default: 0).", false, OptionsCategory::DEBUG_TEST);
@@ -30,10 +30,6 @@ static void SetupWalletToolArgs()
gArgs.AddArg("info", "Get wallet info", false, OptionsCategory::COMMANDS);
gArgs.AddArg("create", "Create new wallet file", false, OptionsCategory::COMMANDS);
-
- // Hidden
- gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
}
static bool WalletAppInit(int argc, char* argv[])
diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp
index 9211a7596b..8a76021a5b 100644
--- a/src/dummywallet.cpp
+++ b/src/dummywallet.cpp
@@ -8,6 +8,10 @@
class CWallet;
+namespace interfaces {
+class Chain;
+}
+
class DummyWalletInit : public WalletInitInterface {
public:
@@ -43,6 +47,11 @@ std::vector<std::shared_ptr<CWallet>> GetWallets()
throw std::logic_error("Wallet function called in non-wallet build.");
}
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning)
+{
+ throw std::logic_error("Wallet function called in non-wallet build.");
+}
+
namespace interfaces {
class Wallet;
diff --git a/src/init.cpp b/src/init.cpp
index e3d5c49538..0013319ad5 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -326,6 +326,9 @@ static void OnRPCStopped()
void SetupServerArgs()
{
+ SetupHelpOptions(gArgs);
+ gArgs.AddArg("-help-debug", "Print help message with debugging options and exit", false, OptionsCategory::DEBUG_TEST); // server-only for now
+
const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
@@ -334,14 +337,11 @@ void SetupServerArgs()
const auto regtestChainParams = CreateChainParams(CBaseChainParams::REGTEST);
// Hidden Options
- std::vector<std::string> hidden_args = {"-h", "-help",
+ std::vector<std::string> hidden_args = {
"-dbcrashratio", "-forcecompactdb",
// GUI args. These will be overwritten by SetupUIArgs for the GUI
"-allowselfsignedrootcertificates", "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-rootcertificates=<file>", "-splash", "-uiplatform"};
- // Set all of the args and their help
- // When adding new options to the categories, please keep and ensure alphabetical ordering.
- gArgs.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-version", "Print version and exit", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-alertnotify=<cmd>", "Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-assumevalid=<hex>", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()), false, OptionsCategory::OPTIONS);
@@ -470,7 +470,6 @@ void SetupServerArgs()
gArgs.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). "
"If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + ListLogCategories() + ".", false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-debugexclude=<category>", strprintf("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."), false, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-help-debug", "Print help message with debugging options and exit", false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS), true, OptionsCategory::DEBUG_TEST);
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index a2b89c3f90..96bde7e9f2 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -42,6 +42,7 @@ class CWallet;
fs::path GetWalletDir();
std::vector<fs::path> ListWalletDir();
std::vector<std::shared_ptr<CWallet>> GetWallets();
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning);
namespace interfaces {
@@ -252,6 +253,10 @@ public:
}
return wallets;
}
+ std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) override
+ {
+ return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warning));
+ }
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
{
return MakeHandler(::uiInterface.InitMessage_connect(fn));
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 54c2d78338..76b93af234 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -192,6 +192,11 @@ public:
//! Return interfaces for accessing wallets (if any).
virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
+ //! Attempts to load a wallet from file or directory.
+ //! The loaded wallet is also notified to handlers previously registered
+ //! with handleLoadWallet.
+ virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) = 0;
+
//! Register handler for init messages.
using InitMessageFn = std::function<void(const std::string& message)>;
virtual std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) = 0;
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 03b47bd3b5..206227b101 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -525,7 +525,7 @@ public:
} // namespace
-std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return MakeUnique<WalletImpl>(wallet); }
+std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? MakeUnique<WalletImpl>(wallet) : nullptr; }
std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, std::vector<std::string> wallet_filenames)
{
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 85d79ee26c..d6c6fd6e98 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -456,7 +456,7 @@ int GuiMain(int argc, char* argv[])
// IMPORTANT if it is no longer a typedef use the normal variant above
qRegisterMetaType< CAmount >("CAmount");
qRegisterMetaType< std::function<void()> >("std::function<void()>");
-
+ qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
/// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
// Command-line options take precedence:
node->setupServerArgs();
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index ba7e8c7daf..f7a4bad916 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -334,6 +334,10 @@ void BitcoinGUI::createActions()
openAction = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("Open &URI..."), this);
openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
+ m_open_wallet_action = new QAction(tr("Open Wallet"), this);
+ m_open_wallet_action->setMenu(new QMenu(this));
+ m_open_wallet_action->setStatusTip(tr("Open a wallet"));
+
showHelpMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/info"), tr("&Command-line options"), this);
showHelpMessageAction->setMenuRole(QAction::NoRole);
showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Bitcoin command-line options").arg(tr(PACKAGE_NAME)));
@@ -361,6 +365,37 @@ void BitcoinGUI::createActions()
connect(usedSendingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedSendingAddresses);
connect(usedReceivingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedReceivingAddresses);
connect(openAction, &QAction::triggered, this, &BitcoinGUI::openClicked);
+ connect(m_open_wallet_action->menu(), &QMenu::aboutToShow, [this] {
+ m_open_wallet_action->menu()->clear();
+ for (std::string path : m_wallet_controller->getWalletsAvailableToOpen()) {
+ QString name = path.empty() ? QString("["+tr("default wallet")+"]") : QString::fromStdString(path);
+ QAction* action = m_open_wallet_action->menu()->addAction(name);
+ connect(action, &QAction::triggered, [this, name, path] {
+ OpenWalletActivity* activity = m_wallet_controller->openWallet(path);
+
+ QProgressDialog* dialog = new QProgressDialog(this);
+ dialog->setLabelText(tr("Opening Wallet <b>%1</b>...").arg(name.toHtmlEscaped()));
+ dialog->setRange(0, 0);
+ dialog->setCancelButton(nullptr);
+ dialog->setWindowModality(Qt::ApplicationModal);
+ dialog->show();
+
+ connect(activity, &OpenWalletActivity::message, this, [this] (QMessageBox::Icon icon, QString text) {
+ QMessageBox box;
+ box.setIcon(icon);
+ box.setText(tr("Open Wallet Failed"));
+ box.setInformativeText(text);
+ box.setStandardButtons(QMessageBox::Ok);
+ box.setDefaultButton(QMessageBox::Ok);
+ connect(this, &QObject::destroyed, &box, &QDialog::accept);
+ box.exec();
+ });
+ connect(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet);
+ connect(activity, &OpenWalletActivity::finished, activity, &QObject::deleteLater);
+ connect(activity, &OpenWalletActivity::finished, dialog, &QObject::deleteLater);
+ });
+ }
+ });
}
#endif // ENABLE_WALLET
@@ -382,6 +417,8 @@ void BitcoinGUI::createMenuBar()
QMenu *file = appMenuBar->addMenu(tr("&File"));
if(walletFrame)
{
+ file->addAction(m_open_wallet_action);
+ file->addSeparator();
file->addAction(openAction);
file->addAction(backupWalletAction);
file->addAction(signMessageAction);
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index c31cefe603..c226494020 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -147,6 +147,7 @@ private:
QAction* openRPCConsoleAction = nullptr;
QAction* openAction = nullptr;
QAction* showHelpMessageAction = nullptr;
+ QAction* m_open_wallet_action{nullptr};
QAction* m_wallet_selector_label_action = nullptr;
QAction* m_wallet_selector_action = nullptr;
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index df2b7a3f9b..3483c75970 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -9,6 +9,7 @@
#include <algorithm>
+#include <QMessageBox>
#include <QMutexLocker>
#include <QThread>
@@ -25,11 +26,17 @@ WalletController::WalletController(interfaces::Node& node, const PlatformStyle*
for (std::unique_ptr<interfaces::Wallet>& wallet : m_node.getWallets()) {
getOrCreateWallet(std::move(wallet));
}
+
+ m_activity_thread.start();
}
// Not using the default destructor because not all member types definitions are
// available in the header, just forward declared.
-WalletController::~WalletController() {}
+WalletController::~WalletController()
+{
+ m_activity_thread.quit();
+ m_activity_thread.wait();
+}
std::vector<WalletModel*> WalletController::getWallets() const
{
@@ -37,6 +44,25 @@ std::vector<WalletModel*> WalletController::getWallets() const
return m_wallets;
}
+std::vector<std::string> WalletController::getWalletsAvailableToOpen() const
+{
+ QMutexLocker locker(&m_mutex);
+ std::vector<std::string> wallets = m_node.listWalletDir();
+ for (WalletModel* wallet_model : m_wallets) {
+ auto it = std::remove(wallets.begin(), wallets.end(), wallet_model->wallet().getWalletName());
+ if (it != wallets.end()) wallets.erase(it);
+ }
+ return wallets;
+}
+
+OpenWalletActivity* WalletController::openWallet(const std::string& name, QWidget* parent)
+{
+ OpenWalletActivity* activity = new OpenWalletActivity(this, name);
+ activity->moveToThread(&m_activity_thread);
+ QMetaObject::invokeMethod(activity, "open", Qt::QueuedConnection);
+ return activity;
+}
+
WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet)
{
QMutexLocker locker(&m_mutex);
@@ -93,3 +119,24 @@ void WalletController::removeAndDeleteWallet(WalletModel* wallet_model)
// CWallet shared pointer.
delete wallet_model;
}
+
+
+OpenWalletActivity::OpenWalletActivity(WalletController* wallet_controller, const std::string& name)
+ : m_wallet_controller(wallet_controller)
+ , m_name(name)
+{}
+
+void OpenWalletActivity::open()
+{
+ std::string error, warning;
+ std::unique_ptr<interfaces::Wallet> wallet = m_wallet_controller->m_node.loadWallet(m_name, error, warning);
+ if (!warning.empty()) {
+ Q_EMIT message(QMessageBox::Warning, QString::fromStdString(warning));
+ }
+ if (wallet) {
+ Q_EMIT opened(m_wallet_controller->getOrCreateWallet(std::move(wallet)));
+ } else {
+ Q_EMIT message(QMessageBox::Critical, QString::fromStdString(error));
+ }
+ Q_EMIT finished();
+}
diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h
index 22b71b07ff..f19c0e1f3d 100644
--- a/src/qt/walletcontroller.h
+++ b/src/qt/walletcontroller.h
@@ -12,7 +12,9 @@
#include <memory>
#include <vector>
+#include <QMessageBox>
#include <QMutex>
+#include <QThread>
class OptionsModel;
class PlatformStyle;
@@ -22,6 +24,8 @@ class Handler;
class Node;
} // namespace interfaces
+class OpenWalletActivity;
+
/**
* Controller between interfaces::Node, WalletModel instances and the GUI.
*/
@@ -37,6 +41,9 @@ public:
~WalletController();
std::vector<WalletModel*> getWallets() const;
+ std::vector<std::string> getWalletsAvailableToOpen() const;
+
+ OpenWalletActivity* openWallet(const std::string& name, QWidget* parent = nullptr);
private Q_SLOTS:
void addWallet(WalletModel* wallet_model);
@@ -48,12 +55,35 @@ Q_SIGNALS:
void coinsSent(WalletModel* wallet_model, SendCoinsRecipient recipient, QByteArray transaction);
private:
+ QThread m_activity_thread;
interfaces::Node& m_node;
const PlatformStyle* const m_platform_style;
OptionsModel* const m_options_model;
mutable QMutex m_mutex;
std::vector<WalletModel*> m_wallets;
std::unique_ptr<interfaces::Handler> m_handler_load_wallet;
+
+ friend class OpenWalletActivity;
+};
+
+class OpenWalletActivity : public QObject
+{
+ Q_OBJECT
+
+public:
+ OpenWalletActivity(WalletController* wallet_controller, const std::string& name);
+
+public Q_SLOTS:
+ void open();
+
+Q_SIGNALS:
+ void message(QMessageBox::Icon icon, const QString text);
+ void finished();
+ void opened(WalletModel* wallet_model);
+
+private:
+ WalletController* const m_wallet_controller;
+ std::string const m_name;
};
#endif // BITCOIN_QT_WALLETCONTROLLER_H
diff --git a/src/util/system.cpp b/src/util/system.cpp
index bb9fcab59e..27ed24d012 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -635,6 +635,12 @@ bool HelpRequested(const ArgsManager& args)
return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help") || args.IsArgSet("-help-debug");
}
+void SetupHelpOptions(ArgsManager& args)
+{
+ args.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
+ args.AddHiddenArgs({"-h", "-help"});
+}
+
static const int screenWidth = 79;
static const int optIndent = 2;
static const int msgIndent = 7;
diff --git a/src/util/system.h b/src/util/system.h
index 17723d427d..54d4cf2e58 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -295,6 +295,9 @@ extern ArgsManager gArgs;
*/
bool HelpRequested(const ArgsManager& args);
+/** Add help options to the args manager */
+void SetupHelpOptions(ArgsManager& args);
+
/**
* Format a string to be used as group of options in help messages
*
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 9bbbdc6132..a9fbed5423 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2555,7 +2555,6 @@ static UniValue loadwallet(const JSONRPCRequest& request)
}.ToString());
WalletLocation location(request.params[0].get_str());
- std::string error;
if (!location.Exists()) {
throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Wallet " + location.GetName() + " not found.");
@@ -2567,18 +2566,9 @@ static UniValue loadwallet(const JSONRPCRequest& request)
}
}
- std::string warning;
- if (!CWallet::Verify(*g_rpc_interfaces->chain, location, false, error, warning)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
- }
-
- std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(*g_rpc_interfaces->chain, location);
- if (!wallet) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Wallet loading failed.");
- }
- AddWallet(wallet);
-
- wallet->postInitProcess();
+ std::string error, warning;
+ std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_interfaces->chain, location, error, warning);
+ if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error);
UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName());
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index d38c15220f..063015d1d8 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -130,6 +130,28 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
}
}
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning)
+{
+ if (!CWallet::Verify(chain, location, false, error, warning)) {
+ error = "Wallet file verification failed: " + error;
+ return nullptr;
+ }
+
+ std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location);
+ if (!wallet) {
+ error = "Wallet loading failed.";
+ return nullptr;
+ }
+ AddWallet(wallet);
+ wallet->postInitProcess();
+ return wallet;
+}
+
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning)
+{
+ return LoadWallet(chain, WalletLocation(name), error, warning);
+}
+
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index c455b7cdad..5846ac0f3e 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -66,6 +66,7 @@ bool RemoveWallet(const std::shared_ptr<CWallet>& wallet);
bool HasWallets();
std::vector<std::shared_ptr<CWallet>> GetWallets();
std::shared_ptr<CWallet> GetWallet(const std::string& name);
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning);
//! Default for -keypool
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py
index c7ae57de86..7d7d251765 100755
--- a/test/functional/p2p_sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
@@ -490,7 +490,7 @@ class SendHeadersTest(BitcoinTestFramework):
# Now announce a header that forks the last two blocks
tip = blocks[0].sha256
- height -= 1
+ height -= 2
blocks = []
# Create extra blocks for later
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index d8f92e2601..999cd72108 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -250,10 +250,6 @@ def main():
# Create base test directory
tmpdir = "%s/test_runner_₿_🏃_%s" % (args.tmpdirprefix, datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
- # If we fixed the command-line and filename encoding issue on Windows, these two lines could be removed
- if config["environment"]["EXEEXT"] == ".exe":
- tmpdir = "%s/test_runner_%s" % (args.tmpdirprefix, datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
-
os.makedirs(tmpdir)
logging.debug("Temporary test directory at %s" % tmpdir)