Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contrib/bitcoin-qt.pro
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ FORMS += \
../src/qt/forms/sendcoinsentry.ui \
../src/qt/forms/signverifymessagedialog.ui \
../src/qt/forms/transactiondescdialog.ui \
../src/qt/forms/createwalletdialog.ui

RESOURCES += \
../src/qt/bitcoin.qrc
4 changes: 4 additions & 0 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ QT_FORMS_UI = \
qt/forms/addressbookpage.ui \
qt/forms/askpassphrasedialog.ui \
qt/forms/coincontroldialog.ui \
qt/forms/createwalletdialog.ui \
qt/forms/editaddressdialog.ui \
qt/forms/helpmessagedialog.ui \
qt/forms/intro.ui \
Expand All @@ -117,6 +118,7 @@ QT_MOC_CPP = \
qt/moc_addressbookpage.cpp \
qt/moc_addresstablemodel.cpp \
qt/moc_askpassphrasedialog.cpp \
qt/moc_createwalletdialog.cpp \
qt/moc_bantablemodel.cpp \
qt/moc_bitcoinaddressvalidator.cpp \
qt/moc_bitcoinamountfield.cpp \
Expand Down Expand Up @@ -202,6 +204,7 @@ BITCOIN_QT_H = \
qt/clientmodel.h \
qt/coincontroldialog.h \
qt/coincontroltreewidget.h \
qt/createwalletdialog.h \
qt/csvmodelwriter.h \
qt/editaddressdialog.h \
qt/guiconstants.h \
Expand Down Expand Up @@ -328,6 +331,7 @@ BITCOIN_QT_WALLET_CPP = \
qt/askpassphrasedialog.cpp \
qt/coincontroldialog.cpp \
qt/coincontroltreewidget.cpp \
qt/createwalletdialog.cpp \
qt/editaddressdialog.cpp \
qt/openuridialog.cpp \
qt/overviewpage.cpp \
Expand Down
7 changes: 7 additions & 0 deletions src/dummywallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#include <stdio.h>
#include <util/system.h>
#include <walletinitinterface.h>
#include <support/allocators/secure.h>

class CWallet;
enum class WalletCreationStatus;

namespace interfaces {
class Chain;
Expand Down Expand Up @@ -74,6 +76,11 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string&
throw std::logic_error("Wallet function called in non-wallet build.");
}

WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result)
{
throw std::logic_error("Wallet function called in non-wallet build.");
}

namespace interfaces {

class Wallet;
Expand Down
9 changes: 9 additions & 0 deletions src/interfaces/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <primitives/block.h>
#include <rpc/server.h>
#include <shutdown.h>
#include <support/allocators/secure.h>
#include <sync.h>
#include <txmempool.h>
#include <ui_interface.h>
Expand All @@ -43,6 +44,7 @@ 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);
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result);

namespace interfaces {

Expand Down Expand Up @@ -258,6 +260,13 @@ class NodeImpl : public Node
{
return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warning));
}
WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::unique_ptr<Wallet>& result) override
{
std::shared_ptr<CWallet> wallet;
WalletCreationStatus status = CreateWallet(*m_interfaces.chain, passphrase, wallet_creation_flags, name, error, warning, wallet);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable status. Also it would be more consistent to make the interface method match the new pattern.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the interface to match the new pattern.

result = MakeWallet(wallet);
return status;
}
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
{
return MakeHandler(::uiInterface.InitMessage_connect(fn));
Expand Down
5 changes: 5 additions & 0 deletions src/interfaces/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <amount.h> // For CAmount
#include <net.h> // For CConnman::NumConnections
#include <netaddress.h> // For Network
#include <support/allocators/secure.h> // For SecureString

#include <functional>
#include <memory>
Expand All @@ -27,6 +28,7 @@ class RPCTimerInterface;
class UniValue;
class proxyType;
struct CNodeStateStats;
enum class WalletCreationStatus;

namespace interfaces {
class Handler;
Expand Down Expand Up @@ -200,6 +202,9 @@ class Node
//! with handleLoadWallet.
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) = 0;

//! Create a wallet from file
virtual WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::unique_ptr<Wallet>& result) = 0;

//! Register handler for init messages.
using InitMessageFn = std::function<void(const std::string& message)>;
virtual std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) = 0;
Expand Down
48 changes: 29 additions & 19 deletions src/qt/askpassphrasedialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
#include <QMessageBox>
#include <QPushButton>

AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) :
AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent, SecureString* passphrase_out) :
QDialog(parent),
ui(new Ui::AskPassphraseDialog),
mode(_mode),
model(nullptr),
fCapsLock(false)
fCapsLock(false),
m_passphrase_out(passphrase_out)
{
ui->setupUi(this);

Expand Down Expand Up @@ -90,7 +91,7 @@ void AskPassphraseDialog::setModel(WalletModel *_model)
void AskPassphraseDialog::accept()
{
SecureString oldpass, newpass1, newpass2;
if(!model)
if (!model && mode != Encrypt)
return;
oldpass.reserve(MAX_PASSPHRASE_SIZE);
newpass1.reserve(MAX_PASSPHRASE_SIZE);
Expand Down Expand Up @@ -119,24 +120,33 @@ void AskPassphraseDialog::accept()
{
if(newpass1 == newpass2)
{
if(model->setWalletEncrypted(true, newpass1))
{
QMessageBox::warning(this, tr("Wallet encrypted"),
QString encryption_reminder = tr("Remember that encrypting your wallet cannot fully protect "
"your bitcoins from being stolen by malware infecting your computer.");
if (m_passphrase_out) {
m_passphrase_out->assign(newpass1);
QMessageBox::warning(this, tr("Wallet to be encrypted"),
"<qt>" +
tr("Your wallet is now encrypted. "
"Remember that encrypting your wallet cannot fully protect "
"your bitcoins from being stolen by malware infecting your computer.") +
"<br><br><b>" +
tr("IMPORTANT: Any previous backups you have made of your wallet file "
"should be replaced with the newly generated, encrypted wallet file. "
"For security reasons, previous backups of the unencrypted wallet file "
"will become useless as soon as you start using the new, encrypted wallet.") +
tr("Your wallet is about to be encrypted. ") + encryption_reminder +
"</b></qt>");
}
else
{
QMessageBox::critical(this, tr("Wallet encryption failed"),
tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."));
} else {
assert(model != nullptr);
if(model->setWalletEncrypted(true, newpass1))
{
QMessageBox::warning(this, tr("Wallet encrypted"),
"<qt>" +
tr("Your wallet is now encrypted. ") + encryption_reminder +
"<br><br><b>" +
tr("IMPORTANT: Any previous backups you have made of your wallet file "
"should be replaced with the newly generated, encrypted wallet file. "
"For security reasons, previous backups of the unencrypted wallet file "
"will become useless as soon as you start using the new, encrypted wallet.") +
"</b></qt>");
}
else
{
QMessageBox::critical(this, tr("Wallet encryption failed"),
tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."));
}
}
QDialog::accept(); // Success
}
Expand Down
5 changes: 4 additions & 1 deletion src/qt/askpassphrasedialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <QDialog>

#include <support/allocators/secure.h>

class WalletModel;

namespace Ui {
Expand All @@ -27,7 +29,7 @@ class AskPassphraseDialog : public QDialog
Decrypt /**< Ask passphrase and decrypt wallet */
};

explicit AskPassphraseDialog(Mode mode, QWidget *parent);
explicit AskPassphraseDialog(Mode mode, QWidget *parent, SecureString* passphrase_out = nullptr);
~AskPassphraseDialog();

void accept();
Expand All @@ -39,6 +41,7 @@ class AskPassphraseDialog : public QDialog
Mode mode;
WalletModel *model;
bool fCapsLock;
SecureString* m_passphrase_out;

private Q_SLOTS:
void textChanged();
Expand Down
37 changes: 14 additions & 23 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <qt/bitcoinunits.h>
#include <qt/clientmodel.h>
#include <qt/createwalletdialog.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/modaloverlay.h>
Expand Down Expand Up @@ -339,6 +340,9 @@ void BitcoinGUI::createActions()
m_close_wallet_action = new QAction(tr("Close Wallet..."), this);
m_close_wallet_action->setStatusTip(tr("Close wallet"));

m_create_wallet_action = new QAction(tr("Create Wallet..."), this);
m_create_wallet_action->setStatusTip(tr("Create a new 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 Bitcoin command-line options").arg(PACKAGE_NAME));
Expand Down Expand Up @@ -379,31 +383,11 @@ void BitcoinGUI::createActions()
continue;
}

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(action, &QAction::triggered, [this, path] {
auto activity = new OpenWalletActivity(m_wallet_controller, this);
connect(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet);
connect(activity, &OpenWalletActivity::finished, activity, &QObject::deleteLater);
connect(activity, &OpenWalletActivity::finished, dialog, &QObject::deleteLater);
bool invoked = QMetaObject::invokeMethod(activity, "open");
assert(invoked);
activity->open(path);
});
}
if (m_open_wallet_menu->isEmpty()) {
Expand All @@ -414,6 +398,12 @@ void BitcoinGUI::createActions()
connect(m_close_wallet_action, &QAction::triggered, [this] {
m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
});
connect(m_create_wallet_action, &QAction::triggered, [this] {
auto activity = new CreateWalletActivity(m_wallet_controller, this);
connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet);
connect(activity, &CreateWalletActivity::finished, activity, &QObject::deleteLater);
activity->create();
});
}
#endif // ENABLE_WALLET

Expand All @@ -435,6 +425,7 @@ void BitcoinGUI::createMenuBar()
QMenu *file = appMenuBar->addMenu(tr("&File"));
if(walletFrame)
{
file->addAction(m_create_wallet_action);
file->addAction(m_open_wallet_action);
file->addAction(m_close_wallet_action);
file->addSeparator();
Expand Down
1 change: 1 addition & 0 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class BitcoinGUI : public QMainWindow
QAction* openRPCConsoleAction = nullptr;
QAction* openAction = nullptr;
QAction* showHelpMessageAction = nullptr;
QAction* m_create_wallet_action{nullptr};
QAction* m_open_wallet_action{nullptr};
QMenu* m_open_wallet_menu{nullptr};
QAction* m_close_wallet_action{nullptr};
Expand Down
61 changes: 61 additions & 0 deletions src/qt/createwalletdialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <qt/createwalletdialog.h>
#include <qt/forms/ui_createwalletdialog.h>

#include <QPushButton>

CreateWalletDialog::CreateWalletDialog(QWidget* parent) :
QDialog(parent),
ui(new Ui::CreateWalletDialog)
{
ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create"));
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
ui->wallet_name_line_edit->setFocus(Qt::ActiveWindowFocusReason);

connect(ui->wallet_name_line_edit, &QLineEdit::textEdited, [this](const QString& text) {
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future this should be moved to a validate() function, because there may be more factors that influence if OK should be enabled.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something for a followup.

});

connect(ui->encrypt_wallet_checkbox, &QCheckBox::toggled, [this](bool checked) {
// Disable disable_privkeys_checkbox when encrypt is set to true, enable it when encrypt is false
ui->disable_privkeys_checkbox->setEnabled(!checked);

// When the disable_privkeys_checkbox is disabled, uncheck it.
if (!ui->disable_privkeys_checkbox->isEnabled()) {
ui->disable_privkeys_checkbox->setChecked(false);
}
});
}

CreateWalletDialog::~CreateWalletDialog()
{
delete ui;
}

QString CreateWalletDialog::walletName() const
{
return ui->wallet_name_line_edit->text();
}

bool CreateWalletDialog::encrypt() const
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: it would be clearer to name this as encryptWallet here and makeBlankWallet on line 58, the way disablePrivateKeys is named.

{
return ui->encrypt_wallet_checkbox->isChecked();
}

bool CreateWalletDialog::disablePrivateKeys() const
{
return ui->disable_privkeys_checkbox->isChecked();
}

bool CreateWalletDialog::blank() const
{
return ui->blank_wallet_checkbox->isChecked();
}
35 changes: 35 additions & 0 deletions src/qt/createwalletdialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_QT_CREATEWALLETDIALOG_H
#define BITCOIN_QT_CREATEWALLETDIALOG_H

#include <QDialog>

class WalletModel;

namespace Ui {
class CreateWalletDialog;
}

/** Dialog for creating wallets
*/
class CreateWalletDialog : public QDialog
{
Q_OBJECT

public:
explicit CreateWalletDialog(QWidget* parent);
virtual ~CreateWalletDialog();

QString walletName() const;
bool encrypt() const;
bool disablePrivateKeys() const;
bool blank() const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: following my comment above, naming these encryptWallet and makeBlankWallet (like disablePrivateKeys) seems more precise/coherent/would improve git grepping.


private:
Ui::CreateWalletDialog *ui;
};

#endif // BITCOIN_QT_CREATEWALLETDIALOG_H
Loading