mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
Merge pull request #4540 from PastaPastaPasta/backport-new-wallet
Backport 15153, 15195
This commit is contained in:
commit
eb95f83096
@ -10,6 +10,10 @@
|
||||
|
||||
class CWallet;
|
||||
|
||||
namespace interfaces {
|
||||
class Chain;
|
||||
}
|
||||
|
||||
class DummyWalletInit : public WalletInitInterface {
|
||||
public:
|
||||
|
||||
@ -89,6 +93,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;
|
||||
|
@ -49,6 +49,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 {
|
||||
|
||||
@ -378,6 +379,11 @@ 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));
|
||||
}
|
||||
|
||||
EVO& evo() override { return m_evo; }
|
||||
LLMQ& llmq() override { return m_llmq; }
|
||||
Masternode::Sync& masternodeSync() override { return m_masternodeSync; }
|
||||
|
@ -253,6 +253,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;
|
||||
|
||||
//! Return interface for accessing evo related handler.
|
||||
virtual EVO& evo() = 0;
|
||||
|
||||
|
@ -544,6 +544,10 @@ public:
|
||||
bool hdEnabled() override { return m_wallet->IsHDEnabled(); }
|
||||
bool IsWalletFlagSet(uint64_t flag) override { return m_wallet->IsWalletFlagSet(flag); }
|
||||
CoinJoin::Client& coinJoin() override { return m_coinjoin; }
|
||||
void remove() override
|
||||
{
|
||||
RemoveWallet(m_wallet);
|
||||
}
|
||||
std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
|
||||
{
|
||||
return MakeHandler(m_wallet->NotifyUnload.connect(fn));
|
||||
@ -610,7 +614,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)
|
||||
{
|
||||
|
@ -266,6 +266,9 @@ public:
|
||||
|
||||
virtual CoinJoin::Client& coinJoin() = 0;
|
||||
|
||||
// Remove wallet.
|
||||
virtual void remove() = 0;
|
||||
|
||||
//! Register handler for unload message.
|
||||
using UnloadFn = std::function<void()>;
|
||||
virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
|
||||
|
@ -427,6 +427,13 @@ void BitcoinGUI::createActions()
|
||||
openAction = new QAction(tr("Open &URI..."), this);
|
||||
openAction->setStatusTip(tr("Open a dash: 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"));
|
||||
|
||||
m_close_wallet_action = new QAction(tr("Close Wallet..."), this);
|
||||
m_close_wallet_action->setStatusTip(tr("Close wallet"));
|
||||
|
||||
showHelpMessageAction = new QAction(tr("&Command-line options"), this);
|
||||
showHelpMessageAction->setMenuRole(QAction::NoRole);
|
||||
showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Dash command-line options").arg(tr(PACKAGE_NAME)));
|
||||
@ -475,6 +482,40 @@ 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);
|
||||
});
|
||||
}
|
||||
});
|
||||
connect(m_close_wallet_action, &QAction::triggered, [this] {
|
||||
m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
|
||||
});
|
||||
}
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
@ -499,6 +540,9 @@ void BitcoinGUI::createMenuBar()
|
||||
QMenu *file = appMenuBar->addMenu(tr("&File"));
|
||||
if(walletFrame)
|
||||
{
|
||||
file->addAction(m_open_wallet_action);
|
||||
file->addAction(m_close_wallet_action);
|
||||
file->addSeparator();
|
||||
file->addAction(openAction);
|
||||
file->addAction(backupWalletAction);
|
||||
file->addAction(signMessageAction);
|
||||
@ -891,6 +935,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
|
||||
usedSendingAddressesAction->setEnabled(enabled);
|
||||
usedReceivingAddressesAction->setEnabled(enabled);
|
||||
openAction->setEnabled(enabled);
|
||||
m_close_wallet_action->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void BitcoinGUI::createTrayIcon()
|
||||
|
@ -159,6 +159,8 @@ private:
|
||||
QAction* showBackupsAction = nullptr;
|
||||
QAction* openAction = nullptr;
|
||||
QAction* showHelpMessageAction = nullptr;
|
||||
QAction* m_open_wallet_action{nullptr};
|
||||
QAction* m_close_wallet_action{nullptr};
|
||||
QAction* showCoinJoinHelpAction = nullptr;
|
||||
QAction* m_wallet_selector_action = nullptr;
|
||||
|
||||
|
@ -479,7 +479,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();
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QMutexLocker>
|
||||
#include <QThread>
|
||||
#include <QWindow>
|
||||
@ -26,11 +27,17 @@ WalletController::WalletController(interfaces::Node& node, OptionsModel* options
|
||||
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
|
||||
{
|
||||
@ -38,6 +45,41 @@ 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;
|
||||
}
|
||||
|
||||
void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent)
|
||||
{
|
||||
QMessageBox box(parent);
|
||||
box.setWindowTitle(tr("Close wallet"));
|
||||
box.setText(tr("Are you sure you wish to close wallet <i>%1</i>?").arg(wallet_model->getDisplayName()));
|
||||
box.setInformativeText(tr("Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled."));
|
||||
box.setStandardButtons(QMessageBox::Yes|QMessageBox::Cancel);
|
||||
box.setDefaultButton(QMessageBox::Yes);
|
||||
if (box.exec() != QMessageBox::Yes) return;
|
||||
|
||||
// First remove wallet from node.
|
||||
wallet_model->wallet().remove();
|
||||
// Now release the model.
|
||||
removeAndDeleteWallet(wallet_model);
|
||||
}
|
||||
|
||||
WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
@ -111,3 +153,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();
|
||||
}
|
||||
|
@ -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,10 @@ public:
|
||||
~WalletController();
|
||||
|
||||
std::vector<WalletModel*> getWallets() const;
|
||||
std::vector<std::string> getWalletsAvailableToOpen() const;
|
||||
|
||||
OpenWalletActivity* openWallet(const std::string& name, QWidget* parent = nullptr);
|
||||
void closeWallet(WalletModel* wallet_model, QWidget* parent = nullptr);
|
||||
|
||||
private Q_SLOTS:
|
||||
void addWallet(WalletModel* wallet_model);
|
||||
@ -48,11 +56,34 @@ Q_SIGNALS:
|
||||
void coinsSent(WalletModel* wallet_model, SendCoinsRecipient recipient, QByteArray transaction);
|
||||
|
||||
private:
|
||||
QThread m_activity_thread;
|
||||
interfaces::Node& m_node;
|
||||
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
|
||||
|
@ -2856,7 +2856,6 @@ static UniValue loadwallet(const JSONRPCRequest& request)
|
||||
);
|
||||
|
||||
WalletLocation location(request.params[0].get_str());
|
||||
std::string error;
|
||||
|
||||
if (!location.Exists()) {
|
||||
throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Wallet " + location.GetName() + " not found.");
|
||||
@ -2868,17 +2867,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.");
|
||||
}
|
||||
|
||||
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());
|
||||
|
@ -149,6 +149,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 uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
|
||||
/** @defgroup mapWallet
|
||||
|
@ -70,6 +70,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);
|
||||
|
||||
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
|
||||
//! -paytxfee default
|
||||
|
Loading…
Reference in New Issue
Block a user