aboutsummaryrefslogtreecommitdiff
path: root/src/qt
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt')
-rw-r--r--src/qt/askpassphrasedialog.cpp38
-rw-r--r--src/qt/clientmodel.cpp2
-rw-r--r--src/qt/optionsdialog.cpp31
-rw-r--r--src/qt/optionsmodel.cpp136
-rw-r--r--src/qt/optionsmodel.h16
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/test/addressbooktests.cpp2
-rw-r--r--src/qt/test/wallettests.cpp2
-rw-r--r--src/qt/walletmodel.cpp7
-rw-r--r--src/qt/walletmodel.h18
10 files changed, 141 insertions, 113 deletions
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index d15aba5cdd..0a96be038b 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -89,11 +89,10 @@ void AskPassphraseDialog::accept()
oldpass.reserve(MAX_PASSPHRASE_SIZE);
newpass1.reserve(MAX_PASSPHRASE_SIZE);
newpass2.reserve(MAX_PASSPHRASE_SIZE);
- // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
- // Alternately, find a way to make this input mlock()'d to begin with.
- oldpass.assign(ui->passEdit1->text().toStdString().c_str());
- newpass1.assign(ui->passEdit2->text().toStdString().c_str());
- newpass2.assign(ui->passEdit3->text().toStdString().c_str());
+
+ oldpass.assign(std::string_view{ui->passEdit1->text().toStdString()});
+ newpass1.assign(std::string_view{ui->passEdit2->text().toStdString()});
+ newpass2.assign(std::string_view{ui->passEdit3->text().toStdString()});
secureClearPassFields();
@@ -154,8 +153,19 @@ void AskPassphraseDialog::accept()
case Unlock:
try {
if (!model->setWalletLocked(false, oldpass)) {
- QMessageBox::critical(this, tr("Wallet unlock failed"),
- tr("The passphrase entered for the wallet decryption was incorrect."));
+ // Check if the passphrase has a null character (see #27067 for details)
+ if (oldpass.find('\0') == std::string::npos) {
+ QMessageBox::critical(this, tr("Wallet unlock failed"),
+ tr("The passphrase entered for the wallet decryption was incorrect."));
+ } else {
+ QMessageBox::critical(this, tr("Wallet unlock failed"),
+ tr("The passphrase entered for the wallet decryption is incorrect. "
+ "It contains a null character (ie - a zero byte). "
+ "If the passphrase was set with a version of this software prior to 25.0, "
+ "please try again with only the characters up to — but not including — "
+ "the first null character. If this is successful, please set a new "
+ "passphrase to avoid this issue in the future."));
+ }
} else {
QDialog::accept(); // Success
}
@@ -174,8 +184,18 @@ void AskPassphraseDialog::accept()
}
else
{
- QMessageBox::critical(this, tr("Wallet encryption failed"),
- tr("The passphrase entered for the wallet decryption was incorrect."));
+ // Check if the old passphrase had a null character (see #27067 for details)
+ if (oldpass.find('\0') == std::string::npos) {
+ QMessageBox::critical(this, tr("Passphrase change failed"),
+ tr("The passphrase entered for the wallet decryption was incorrect."));
+ } else {
+ QMessageBox::critical(this, tr("Passphrase change failed"),
+ tr("The old passphrase entered for the wallet decryption is incorrect. "
+ "It contains a null character (ie - a zero byte). "
+ "If the passphrase was set with a version of this software prior to 25.0, "
+ "please try again with only the characters up to — but not including — "
+ "the first null character."));
+ }
}
}
else
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 69ed5d3a90..8411ec4696 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -280,7 +280,7 @@ bool ClientModel::getProxyInfo(std::string& ip_port) const
{
Proxy ipv4, ipv6;
if (m_node.getProxy((Network) 1, ipv4) && m_node.getProxy((Network) 2, ipv6)) {
- ip_port = ipv4.proxy.ToStringIPPort();
+ ip_port = ipv4.proxy.ToStringAddrPort();
return true;
}
return false;
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 53b0c3832b..6dec4b2e42 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -406,24 +406,21 @@ void OptionsDialog::updateProxyValidationState()
void OptionsDialog::updateDefaultProxyNets()
{
+ CNetAddr ui_proxy_netaddr;
+ LookupHost(ui->proxyIp->text().toStdString(), ui_proxy_netaddr, /*fAllowLookup=*/false);
+ const CService ui_proxy{ui_proxy_netaddr, ui->proxyPort->text().toUShort()};
+
Proxy proxy;
- std::string strProxy;
- QString strDefaultProxyGUI;
-
- model->node().getProxy(NET_IPV4, proxy);
- strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
- strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
- (strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachIPv4->setChecked(true) : ui->proxyReachIPv4->setChecked(false);
-
- model->node().getProxy(NET_IPV6, proxy);
- strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
- strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
- (strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachIPv6->setChecked(true) : ui->proxyReachIPv6->setChecked(false);
-
- model->node().getProxy(NET_ONION, proxy);
- strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
- strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
- (strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachTor->setChecked(true) : ui->proxyReachTor->setChecked(false);
+ bool has_proxy;
+
+ has_proxy = model->node().getProxy(NET_IPV4, proxy);
+ ui->proxyReachIPv4->setChecked(has_proxy && proxy.proxy == ui_proxy);
+
+ has_proxy = model->node().getProxy(NET_IPV6, proxy);
+ ui->proxyReachIPv6->setChecked(has_proxy && proxy.proxy == ui_proxy);
+
+ has_proxy = model->node().getProxy(NET_ONION, proxy);
+ ui->proxyReachTor->setChecked(has_proxy && proxy.proxy == ui_proxy);
}
ProxyAddressValidator::ProxyAddressValidator(QObject *parent) :
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 761351468e..bee8fafddc 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -18,6 +18,7 @@
#include <netbase.h>
#include <txdb.h> // for -dbcache defaults
#include <util/string.h>
+#include <util/system.h>
#include <validation.h> // For DEFAULT_SCRIPTCHECK_THREADS
#include <wallet/wallet.h> // For DEFAULT_SPEND_ZEROCONF_CHANGE
@@ -59,7 +60,7 @@ static const char* SettingName(OptionsModel::OptionID option)
}
/** Call node.updateRwSetting() with Bitcoin 22.x workaround. */
-static void UpdateRwSetting(interfaces::Node& node, OptionsModel::OptionID option, const util::SettingsValue& value)
+static void UpdateRwSetting(interfaces::Node& node, OptionsModel::OptionID option, const std::string& suffix, const util::SettingsValue& value)
{
if (value.isNum() &&
(option == OptionsModel::DatabaseCache ||
@@ -73,9 +74,9 @@ static void UpdateRwSetting(interfaces::Node& node, OptionsModel::OptionID optio
// in later releases by https://github.com/bitcoin/bitcoin/pull/24498.
// If new numeric settings are added, they can be written as numbers
// instead of strings, because bitcoin 22.x will not try to read these.
- node.updateRwSetting(SettingName(option), value.getValStr());
+ node.updateRwSetting(SettingName(option) + suffix, value.getValStr());
} else {
- node.updateRwSetting(SettingName(option), value);
+ node.updateRwSetting(SettingName(option) + suffix, value);
}
}
@@ -131,13 +132,6 @@ void OptionsModel::addOverriddenOption(const std::string &option)
bool OptionsModel::Init(bilingual_str& error)
{
// Initialize display settings from stored settings.
- m_prune_size_gb = PruneSizeGB(node().getPersistentSetting("prune"));
- ProxySetting proxy = ParseProxyString(SettingToString(node().getPersistentSetting("proxy"), GetDefaultProxyAddress().toStdString()));
- m_proxy_ip = proxy.ip;
- m_proxy_port = proxy.port;
- ProxySetting onion = ParseProxyString(SettingToString(node().getPersistentSetting("onion"), GetDefaultProxyAddress().toStdString()));
- m_onion_ip = onion.ip;
- m_onion_port = onion.port;
language = QString::fromStdString(SettingToString(node().getPersistentSetting("lang"), ""));
checkAndMigrate();
@@ -320,8 +314,6 @@ void OptionsModel::SetPruneTargetGB(int prune_target_gb)
const util::SettingsValue cur_value = node().getPersistentSetting("prune");
const util::SettingsValue new_value = PruneSetting(prune_target_gb > 0, prune_target_gb);
- m_prune_size_gb = prune_target_gb;
-
// Force setting to take effect. It is still safe to change the value at
// this point because this function is only called after the intro screen is
// shown, before the node starts.
@@ -334,7 +326,12 @@ void OptionsModel::SetPruneTargetGB(int prune_target_gb)
PruneSizeGB(cur_value) != PruneSizeGB(new_value)) {
// Call UpdateRwSetting() instead of setOption() to avoid setting
// RestartRequired flag
- UpdateRwSetting(node(), Prune, new_value);
+ UpdateRwSetting(node(), Prune, "", new_value);
+ }
+
+ // Keep previous pruning size, if pruning was disabled.
+ if (PruneEnabled(cur_value)) {
+ UpdateRwSetting(node(), Prune, "-prev", PruneEnabled(new_value) ? util::SettingsValue{} : cur_value);
}
}
@@ -362,9 +359,9 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
return successful;
}
-QVariant OptionsModel::getOption(OptionID option) const
+QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) const
{
- auto setting = [&]{ return node().getPersistentSetting(SettingName(option)); };
+ auto setting = [&]{ return node().getPersistentSetting(SettingName(option) + suffix); };
QSettings settings;
switch (option) {
@@ -391,19 +388,30 @@ QVariant OptionsModel::getOption(OptionID option) const
// default proxy
case ProxyUse:
+ case ProxyUseTor:
return ParseProxyString(SettingToString(setting(), "")).is_set;
case ProxyIP:
- return m_proxy_ip;
+ case ProxyIPTor: {
+ ProxySetting proxy = ParseProxyString(SettingToString(setting(), ""));
+ if (proxy.is_set) {
+ return proxy.ip;
+ } else if (suffix.empty()) {
+ return getOption(option, "-prev");
+ } else {
+ return ParseProxyString(GetDefaultProxyAddress().toStdString()).ip;
+ }
+ }
case ProxyPort:
- return m_proxy_port;
-
- // separate Tor proxy
- case ProxyUseTor:
- return ParseProxyString(SettingToString(setting(), "")).is_set;
- case ProxyIPTor:
- return m_onion_ip;
- case ProxyPortTor:
- return m_onion_port;
+ case ProxyPortTor: {
+ ProxySetting proxy = ParseProxyString(SettingToString(setting(), ""));
+ if (proxy.is_set) {
+ return proxy.port;
+ } else if (suffix.empty()) {
+ return getOption(option, "-prev");
+ } else {
+ return ParseProxyString(GetDefaultProxyAddress().toStdString()).port;
+ }
+ }
#ifdef ENABLE_WALLET
case SpendZeroConfChange:
@@ -428,7 +436,9 @@ QVariant OptionsModel::getOption(OptionID option) const
case Prune:
return PruneEnabled(setting());
case PruneSize:
- return m_prune_size_gb;
+ return PruneEnabled(setting()) ? PruneSizeGB(setting()) :
+ suffix.empty() ? getOption(option, "-prev") :
+ DEFAULT_PRUNE_TARGET_GB;
case DatabaseCache:
return qlonglong(SettingToInt(setting(), nDefaultDbCache));
case ThreadsScriptVerif:
@@ -444,10 +454,10 @@ QVariant OptionsModel::getOption(OptionID option) const
}
}
-bool OptionsModel::setOption(OptionID option, const QVariant& value)
+bool OptionsModel::setOption(OptionID option, const QVariant& value, const std::string& suffix)
{
- auto changed = [&] { return value.isValid() && value != getOption(option); };
- auto update = [&](const util::SettingsValue& value) { return UpdateRwSetting(node(), option, value); };
+ auto changed = [&] { return value.isValid() && value != getOption(option, suffix); };
+ auto update = [&](const util::SettingsValue& value) { return UpdateRwSetting(node(), option, suffix, value); };
bool successful = true; /* set to false on parse error */
QSettings settings;
@@ -485,52 +495,60 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value)
// default proxy
case ProxyUse:
if (changed()) {
- update(ProxyString(value.toBool(), m_proxy_ip, m_proxy_port));
- setRestartRequired(true);
+ if (suffix.empty() && !value.toBool()) setOption(option, true, "-prev");
+ update(ProxyString(value.toBool(), getOption(ProxyIP).toString(), getOption(ProxyPort).toString()));
+ if (suffix.empty() && value.toBool()) UpdateRwSetting(node(), option, "-prev", {});
+ if (suffix.empty()) setRestartRequired(true);
}
break;
case ProxyIP:
if (changed()) {
- m_proxy_ip = value.toString();
- if (getOption(ProxyUse).toBool()) {
- update(ProxyString(true, m_proxy_ip, m_proxy_port));
- setRestartRequired(true);
+ if (suffix.empty() && !getOption(ProxyUse).toBool()) {
+ setOption(option, value, "-prev");
+ } else {
+ update(ProxyString(true, value.toString(), getOption(ProxyPort).toString()));
}
+ if (suffix.empty() && getOption(ProxyUse).toBool()) setRestartRequired(true);
}
break;
case ProxyPort:
if (changed()) {
- m_proxy_port = value.toString();
- if (getOption(ProxyUse).toBool()) {
- update(ProxyString(true, m_proxy_ip, m_proxy_port));
- setRestartRequired(true);
+ if (suffix.empty() && !getOption(ProxyUse).toBool()) {
+ setOption(option, value, "-prev");
+ } else {
+ update(ProxyString(true, getOption(ProxyIP).toString(), value.toString()));
}
+ if (suffix.empty() && getOption(ProxyUse).toBool()) setRestartRequired(true);
}
break;
// separate Tor proxy
case ProxyUseTor:
if (changed()) {
- update(ProxyString(value.toBool(), m_onion_ip, m_onion_port));
- setRestartRequired(true);
+ if (suffix.empty() && !value.toBool()) setOption(option, true, "-prev");
+ update(ProxyString(value.toBool(), getOption(ProxyIPTor).toString(), getOption(ProxyPortTor).toString()));
+ if (suffix.empty() && value.toBool()) UpdateRwSetting(node(), option, "-prev", {});
+ if (suffix.empty()) setRestartRequired(true);
}
break;
case ProxyIPTor:
if (changed()) {
- m_onion_ip = value.toString();
- if (getOption(ProxyUseTor).toBool()) {
- update(ProxyString(true, m_onion_ip, m_onion_port));
- setRestartRequired(true);
+ if (suffix.empty() && !getOption(ProxyUseTor).toBool()) {
+ setOption(option, value, "-prev");
+ } else {
+ update(ProxyString(true, value.toString(), getOption(ProxyPortTor).toString()));
}
+ if (suffix.empty() && getOption(ProxyUseTor).toBool()) setRestartRequired(true);
}
break;
case ProxyPortTor:
if (changed()) {
- m_onion_port = value.toString();
- if (getOption(ProxyUseTor).toBool()) {
- update(ProxyString(true, m_onion_ip, m_onion_port));
- setRestartRequired(true);
+ if (suffix.empty() && !getOption(ProxyUseTor).toBool()) {
+ setOption(option, value, "-prev");
+ } else {
+ update(ProxyString(true, getOption(ProxyIPTor).toString(), value.toString()));
}
+ if (suffix.empty() && getOption(ProxyUseTor).toBool()) setRestartRequired(true);
}
break;
@@ -584,17 +602,20 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value)
break;
case Prune:
if (changed()) {
- update(PruneSetting(value.toBool(), m_prune_size_gb));
- setRestartRequired(true);
+ if (suffix.empty() && !value.toBool()) setOption(option, true, "-prev");
+ update(PruneSetting(value.toBool(), getOption(PruneSize).toInt()));
+ if (suffix.empty() && value.toBool()) UpdateRwSetting(node(), option, "-prev", {});
+ if (suffix.empty()) setRestartRequired(true);
}
break;
case PruneSize:
if (changed()) {
- m_prune_size_gb = ParsePruneSizeGB(value);
- if (getOption(Prune).toBool()) {
- update(PruneSetting(true, m_prune_size_gb));
- setRestartRequired(true);
+ if (suffix.empty() && !getOption(Prune).toBool()) {
+ setOption(option, value, "-prev");
+ } else {
+ update(PruneSetting(true, ParsePruneSizeGB(value)));
}
+ if (suffix.empty() && getOption(Prune).toBool()) setRestartRequired(true);
}
break;
case DatabaseCache:
@@ -648,6 +669,11 @@ bool OptionsModel::isRestartRequired() const
return settings.value("fRestartRequired", false).toBool();
}
+bool OptionsModel::hasSigner()
+{
+ return gArgs.GetArg("-signer", "") != "";
+}
+
void OptionsModel::checkAndMigrate()
{
// Migration of default values
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 848966574d..f28a1087ba 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -82,8 +82,8 @@ public:
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override;
- QVariant getOption(OptionID option) const;
- bool setOption(OptionID option, const QVariant& value);
+ QVariant getOption(OptionID option, const std::string& suffix="") const;
+ bool setOption(OptionID option, const QVariant& value, const std::string& suffix="");
/** Updates current unit in memory, settings and emits displayUnitChanged(new_unit) signal */
void setDisplayUnit(const QVariant& new_unit);
@@ -99,6 +99,9 @@ public:
bool getEnablePSBTControls() const { return m_enable_psbt_controls; }
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
+ /** Whether -signer was set or not */
+ bool hasSigner();
+
/* Explicit setters */
void SetPruneTargetGB(int prune_target_gb);
@@ -123,15 +126,6 @@ private:
bool m_enable_psbt_controls;
bool m_mask_values;
- //! In-memory settings for display. These are stored persistently by the
- //! bitcoin node but it's also nice to store them in memory to prevent them
- //! getting cleared when enable/disable toggles are used in the GUI.
- int m_prune_size_gb;
- QString m_proxy_ip;
- QString m_proxy_port;
- QString m_onion_ip;
- QString m_onion_port;
-
/* settings that were overridden by command-line */
QString strOverriddenByCommandLine;
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 33145cc48d..89dd0ada62 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -203,7 +203,7 @@ void SendCoinsDialog::setModel(WalletModel *_model)
if (model->wallet().hasExternalSigner()) {
//: "device" usually means a hardware wallet.
ui->sendButton->setText(tr("Sign on device"));
- if (gArgs.GetArg("-signer", "") != "") {
+ if (model->getOptionsModel()->hasSigner()) {
ui->sendButton->setEnabled(true);
ui->sendButton->setToolTip(tr("Connect your hardware wallet first."));
} else {
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index 049326070e..d005e08d14 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -75,7 +75,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
auto wallet_loader = interfaces::MakeWalletLoader(*test.m_node.chain, *Assert(test.m_node.args));
test.m_node.wallet_loader = wallet_loader.get();
node.setContext(&test.m_node);
- const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", gArgs, CreateMockWalletDatabase());
+ const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
{
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 15fe37c164..62f2019438 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -159,7 +159,7 @@ void TestGUI(interfaces::Node& node)
auto wallet_loader = interfaces::MakeWalletLoader(*test.m_node.chain, *Assert(test.m_node.args));
test.m_node.wallet_loader = wallet_loader.get();
node.setContext(&test.m_node);
- const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", gArgs, CreateMockWalletDatabase());
+ const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", CreateMockWalletDatabase());
wallet->LoadWallet();
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
{
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index cb8491e27a..3c69d46b7e 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -477,13 +477,6 @@ WalletModel::UnlockContext::~UnlockContext()
}
}
-void WalletModel::UnlockContext::CopyFrom(UnlockContext&& rhs)
-{
- // Transfer context; old object no longer relocks wallet
- *this = rhs;
- rhs.relock = false;
-}
-
bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
{
CCoinControl coin_control;
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 604a9e03c8..17a39349f3 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -111,7 +111,7 @@ public:
bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString());
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass);
- // RAI object for unlocking wallet, returned by requestUnlock()
+ // RAII object for unlocking wallet, returned by requestUnlock()
class UnlockContext
{
public:
@@ -120,18 +120,16 @@ public:
bool isValid() const { return valid; }
- // Copy constructor is disabled.
+ // Disable unused copy/move constructors/assignments explicitly.
UnlockContext(const UnlockContext&) = delete;
- // Move operator and constructor transfer the context
- UnlockContext(UnlockContext&& obj) { CopyFrom(std::move(obj)); }
- UnlockContext& operator=(UnlockContext&& rhs) { CopyFrom(std::move(rhs)); return *this; }
+ UnlockContext(UnlockContext&&) = delete;
+ UnlockContext& operator=(const UnlockContext&) = delete;
+ UnlockContext& operator=(UnlockContext&&) = delete;
+
private:
WalletModel *wallet;
- bool valid;
- mutable bool relock; // mutable, as it can be set to false by copying
-
- UnlockContext& operator=(const UnlockContext&) = default;
- void CopyFrom(UnlockContext&& rhs);
+ const bool valid;
+ const bool relock;
};
UnlockContext requestUnlock();