Skip to content

Commit 8c6c481

Browse files
laanwjMunkybooty
authored andcommitted
Merge bitcoin#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. bitcoin#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 bitcoin#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
1 parent ae81529 commit 8c6c481

File tree

7 files changed

+43
-2
lines changed

7 files changed

+43
-2
lines changed

src/interfaces/wallet.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,10 @@ class WalletImpl : public Wallet
541541
{
542542
return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
543543
}
544+
std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) override
545+
{
546+
return MakeHandler(m_wallet.NotifyCanGetAddressesChanged.connect(fn));
547+
}
544548

545549
std::shared_ptr<CWallet> m_shared_wallet;
546550
CWallet& m_wallet;

src/interfaces/wallet.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ class Wallet
300300
//! Register handler for watchonly changed messages.
301301
using WatchOnlyChangedFn = std::function<void(bool have_watch_only)>;
302302
virtual std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0;
303+
304+
//! Register handler for keypool changed messages.
305+
using CanGetAddressesChangedFn = std::function<void()>;
306+
virtual std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) = 0;
303307
};
304308

305309
//! 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
@@ -87,8 +87,13 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
8787
// Last 2 columns are set by the columnResizingFixer, when the table geometry is ready.
8888
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this);
8989

90-
// eventually disable the main receive button if private key operations are disabled
91-
ui->receiveButton->setEnabled(!model->privateKeysDisabled());
90+
// Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
91+
ui->receiveButton->setEnabled(model->canGetAddresses());
92+
93+
// Enable/disable the receive button if the wallet is now able/unable to give out new addresses.
94+
connect(model, &WalletModel::canGetAddressesChanged, [this] {
95+
ui->receiveButton->setEnabled(model->canGetAddresses());
96+
});
9297
}
9398
}
9499

src/qt/walletmodel.cpp

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

490+
static void NotifyCanGetAddressesChanged(WalletModel* walletmodel)
491+
{
492+
QMetaObject::invokeMethod(walletmodel, "canGetAddressesChanged");
493+
}
494+
490495
void WalletModel::subscribeToCoreSignals()
491496
{
492497
// Connect signals to wallet
@@ -498,6 +503,7 @@ void WalletModel::subscribeToCoreSignals()
498503
m_handler_chainlock_received = m_wallet->handleChainLockReceived(std::bind(NotifyChainLockReceived, this, std::placeholders::_1));
499504
m_handler_show_progress = m_wallet->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2));
500505
m_handler_watch_only_changed = m_wallet->handleWatchOnlyChanged(std::bind(NotifyWatchonlyChanged, this, std::placeholders::_1));
506+
m_handler_can_get_addrs_changed = m_wallet->handleCanGetAddressesChanged(boost::bind(NotifyCanGetAddressesChanged, this));
501507
}
502508

503509
void WalletModel::unsubscribeFromCoreSignals()
@@ -511,6 +517,7 @@ void WalletModel::unsubscribeFromCoreSignals()
511517
m_handler_chainlock_received->disconnect();
512518
m_handler_show_progress->disconnect();
513519
m_handler_watch_only_changed->disconnect();
520+
m_handler_can_get_addrs_changed->disconnect();
514521
}
515522

516523
// WalletModel::UnlockContext implementation
@@ -597,6 +604,16 @@ bool WalletModel::privateKeysDisabled() const
597604
return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
598605
}
599606

607+
bool WalletModel::canGetAddresses() const
608+
{
609+
// The wallet can provide a fresh address if:
610+
// * hdEnabled(): an HD seed is present; or
611+
// * it is a legacy wallet, because:
612+
// * !hdEnabled(): an HD seed is not present; and
613+
// * !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS): private keys have not been disabled (which results in hdEnabled() == true)
614+
return m_wallet->hdEnabled() || (!m_wallet->hdEnabled() && !m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
615+
}
616+
600617
QString WalletModel::getWalletName() const
601618
{
602619
return QString::fromStdString(m_wallet->getWalletName());

src/qt/walletmodel.h

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

197197
static bool isWalletEnabled();
198198
bool privateKeysDisabled() const;
199+
bool canGetAddresses() const;
199200

200201
int getNumBlocks() const;
201202
int getNumISLocks() const;
@@ -223,6 +224,7 @@ class WalletModel : public QObject
223224
std::unique_ptr<interfaces::Handler> m_handler_chainlock_received;
224225
std::unique_ptr<interfaces::Handler> m_handler_show_progress;
225226
std::unique_ptr<interfaces::Handler> m_handler_watch_only_changed;
227+
std::unique_ptr<interfaces::Handler> m_handler_can_get_addrs_changed;
226228
interfaces::Node& m_node;
227229

228230
bool fHaveWatchOnly;
@@ -276,6 +278,9 @@ class WalletModel : public QObject
276278
// Signal that wallet is about to be removed
277279
void unload();
278280

281+
// Notify that there are now keys in the keypool
282+
void canGetAddressesChanged();
283+
279284
public Q_SLOTS:
280285
/* Wallet status might have changed */
281286
void updateStatus();

src/wallet/wallet.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4345,6 +4345,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
43454345
uiInterface.InitMessage(strMsg);
43464346
}
43474347
}
4348+
NotifyCanGetAddressesChanged();
43484349
return true;
43494350
}
43504351

@@ -4386,6 +4387,7 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
43864387
m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
43874388
WalletLogPrintf("keypool reserve %d\n", nIndex);
43884389
}
4390+
NotifyCanGetAddressesChanged();
43894391
return true;
43904392
}
43914393

@@ -4414,6 +4416,7 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey)
44144416
setExternalKeyPool.insert(nIndex);
44154417
}
44164418
m_pool_key_to_index[pubkey.GetID()] = nIndex;
4419+
NotifyCanGetAddressesChanged();
44174420
}
44184421
WalletLogPrintf("keypool return %d\n", nIndex);
44194422
}

src/wallet/wallet.h

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

1238+
/** Keypool has new keys */
1239+
boost::signals2::signal<void ()> NotifyCanGetAddressesChanged;
1240+
12381241
/** IS-lock received */
12391242
boost::signals2::signal<void ()> NotifyISLockReceived;
12401243

0 commit comments

Comments
 (0)