Skip to content

Commit 7c09e20

Browse files
committed
Merge #15225: GUI: Change the receive button to respond to keypool state changing
2bc4c3e Notify the GUI that the keypool has changed to set the receive button (Andrew Chow) 14bcdbe Check for more than private keys disabled to show receive button (Andrew Chow) Pull request description: Currently the Receive button in the GUI is displayed enabled or disabled by the initial state of the wallet when the wallet is first loaded. The button is only enabled or disabled depending on whether the disable private keys flag is set when the wallet is loaded. However, future changes to the wallet means that this initial state and check may no longer be accurate. #14938 introduces empty wallets which do not have private keys. An empty wallet that is loaded should have the Receive button disabled, and then it should become enabled once `sethdseed` is used so that a keypool can be generated and new keys generated. Likewise, with #14075, a wallet can be loaded with no keypool initially, so the button should be disabled. Later, public keys can be imported into the keypool, at which time the button should become enabled. When the keypool runs out again (no new keys are generated as the keypool only consists of imports), the button should become disabled. This PR makes it so that the button becomes enabled and disabled as the keypool state changes. The check for whether to enable or disable the receive button has changed to checking whether it is possible to get new keys. It now checks for whether the wallet has an HD seed and, if not, whether the private keys are disabled. When an action happens which would make it possible for a new address to be retrieved or make it possible for a no more addresses to be retrieved, a signal is emitted which has the GUI recheck the conditions for the Receive button. These actions are setting a new HD seed, topping up the keypool, retrieving a key from the keypool, and returning a key to the keypool. Tree-SHA512: eff15a5337f4c64ecd7169414fb47053c04f6a0f0130341b6dd9799ac4d79f451e25284701c668971fca33f0909d5352a474a2c12349375bedfdb59b63077d50
2 parents 36aeb43 + 2bc4c3e commit 7c09e20

File tree

7 files changed

+44
-2
lines changed

7 files changed

+44
-2
lines changed

src/interfaces/wallet.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,10 @@ class WalletImpl : public Wallet
493493
{
494494
return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
495495
}
496+
std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) override
497+
{
498+
return MakeHandler(m_wallet.NotifyCanGetAddressesChanged.connect(fn));
499+
}
496500

497501
std::shared_ptr<CWallet> m_shared_wallet;
498502
CWallet& m_wallet;

src/interfaces/wallet.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ class Wallet
271271
//! Register handler for watchonly changed messages.
272272
using WatchOnlyChangedFn = std::function<void(bool have_watch_only)>;
273273
virtual std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0;
274+
275+
//! Register handler for keypool changed messages.
276+
using CanGetAddressesChangedFn = std::function<void()>;
277+
virtual std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) = 0;
274278
};
275279

276280
//! Tracking object returned by CreateTransaction and passed to CommitTransaction.

src/qt/receivecoinsdialog.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,13 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
100100
ui->useBech32->setCheckState(Qt::Unchecked);
101101
}
102102

103-
// eventually disable the main receive button if private key operations are disabled
104-
ui->receiveButton->setEnabled(!model->privateKeysDisabled());
103+
// Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
104+
ui->receiveButton->setEnabled(model->canGetAddresses());
105+
106+
// Enable/disable the receive button if the wallet is now able/unable to give out new addresses.
107+
connect(model, &WalletModel::canGetAddressesChanged, [this] {
108+
ui->receiveButton->setEnabled(model->canGetAddresses());
109+
});
105110
}
106111
}
107112

src/qt/walletmodel.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,11 @@ static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly
423423
Q_ARG(bool, fHaveWatchonly));
424424
}
425425

426+
static void NotifyCanGetAddressesChanged(WalletModel* walletmodel)
427+
{
428+
QMetaObject::invokeMethod(walletmodel, "canGetAddressesChanged");
429+
}
430+
426431
void WalletModel::subscribeToCoreSignals()
427432
{
428433
// Connect signals to wallet
@@ -432,6 +437,7 @@ void WalletModel::subscribeToCoreSignals()
432437
m_handler_transaction_changed = m_wallet->handleTransactionChanged(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2));
433438
m_handler_show_progress = m_wallet->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2));
434439
m_handler_watch_only_changed = m_wallet->handleWatchOnlyChanged(std::bind(NotifyWatchonlyChanged, this, std::placeholders::_1));
440+
m_handler_can_get_addrs_changed = m_wallet->handleCanGetAddressesChanged(boost::bind(NotifyCanGetAddressesChanged, this));
435441
}
436442

437443
void WalletModel::unsubscribeFromCoreSignals()
@@ -443,6 +449,7 @@ void WalletModel::unsubscribeFromCoreSignals()
443449
m_handler_transaction_changed->disconnect();
444450
m_handler_show_progress->disconnect();
445451
m_handler_watch_only_changed->disconnect();
452+
m_handler_can_get_addrs_changed->disconnect();
446453
}
447454

448455
// WalletModel::UnlockContext implementation
@@ -571,6 +578,16 @@ bool WalletModel::privateKeysDisabled() const
571578
return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
572579
}
573580

581+
bool WalletModel::canGetAddresses() const
582+
{
583+
// The wallet can provide a fresh address if:
584+
// * hdEnabled(): an HD seed is present; or
585+
// * it is a legacy wallet, because:
586+
// * !hdEnabled(): an HD seed is not present; and
587+
// * !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS): private keys have not been disabled (which results in hdEnabled() == true)
588+
return m_wallet->hdEnabled() || (!m_wallet->hdEnabled() && !m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
589+
}
590+
574591
QString WalletModel::getWalletName() const
575592
{
576593
return QString::fromStdString(m_wallet->getWalletName());

src/qt/walletmodel.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ class WalletModel : public QObject
214214

215215
static bool isWalletEnabled();
216216
bool privateKeysDisabled() const;
217+
bool canGetAddresses() const;
217218

218219
interfaces::Node& node() const { return m_node; }
219220
interfaces::Wallet& wallet() const { return *m_wallet; }
@@ -232,6 +233,7 @@ class WalletModel : public QObject
232233
std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
233234
std::unique_ptr<interfaces::Handler> m_handler_show_progress;
234235
std::unique_ptr<interfaces::Handler> m_handler_watch_only_changed;
236+
std::unique_ptr<interfaces::Handler> m_handler_can_get_addrs_changed;
235237
interfaces::Node& m_node;
236238

237239
bool fHaveWatchOnly;
@@ -283,6 +285,9 @@ class WalletModel : public QObject
283285
// Signal that wallet is about to be removed
284286
void unload();
285287

288+
// Notify that there are now keys in the keypool
289+
void canGetAddressesChanged();
290+
286291
public Q_SLOTS:
287292
/* Wallet status might have changed */
288293
void updateStatus();

src/wallet/wallet.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,7 @@ void CWallet::SetHDSeed(const CPubKey& seed)
13981398
newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
13991399
newHdChain.seed_id = seed.GetID();
14001400
SetHDChain(newHdChain, false);
1401+
NotifyCanGetAddressesChanged();
14011402
}
14021403

14031404
void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
@@ -3335,6 +3336,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
33353336
WalletLogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size(), setInternalKeyPool.size());
33363337
}
33373338
}
3339+
NotifyCanGetAddressesChanged();
33383340
return true;
33393341
}
33403342

@@ -3379,6 +3381,7 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
33793381
m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
33803382
WalletLogPrintf("keypool reserve %d\n", nIndex);
33813383
}
3384+
NotifyCanGetAddressesChanged();
33823385
return true;
33833386
}
33843387

@@ -3403,6 +3406,7 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey)
34033406
setExternalKeyPool.insert(nIndex);
34043407
}
34053408
m_pool_key_to_index[pubkey.GetID()] = nIndex;
3409+
NotifyCanGetAddressesChanged();
34063410
}
34073411
WalletLogPrintf("keypool return %d\n", nIndex);
34083412
}

src/wallet/wallet.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,9 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
10941094
/** Watch-only address added */
10951095
boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
10961096

1097+
/** Keypool has new keys */
1098+
boost::signals2::signal<void ()> NotifyCanGetAddressesChanged;
1099+
10971100
/** Inquire whether this wallet broadcasts transactions. */
10981101
bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
10991102
/** Set whether this wallet broadcasts transactions. */

0 commit comments

Comments
 (0)