From 14bcdbe09cffaef9bcc51dd9de1645db3f0a93db Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Mon, 21 Jan 2019 16:49:33 -0500 Subject: [PATCH 1/2] Check for more than private keys disabled to show receive button --- src/qt/receivecoinsdialog.cpp | 2 +- src/qt/walletmodel.cpp | 5 +++++ src/qt/walletmodel.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index bc96b5a6f..8942188dc 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -101,7 +101,7 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model) } // eventually disable the main receive button if private key operations are disabled - ui->receiveButton->setEnabled(!model->privateKeysDisabled()); + ui->receiveButton->setEnabled(model->canGetAddresses()); } } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index f13915204..73fce0255 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -571,6 +571,11 @@ bool WalletModel::privateKeysDisabled() const return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS); } +bool WalletModel::canGetAddresses() const +{ + return m_wallet->hdEnabled() || (!m_wallet->hdEnabled() && !m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); +} + QString WalletModel::getWalletName() const { return QString::fromStdString(m_wallet->getWalletName()); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index c3c8f3690..8d7b210d2 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -214,6 +214,7 @@ public: static bool isWalletEnabled(); bool privateKeysDisabled() const; + bool canGetAddresses() const; interfaces::Node& node() const { return m_node; } interfaces::Wallet& wallet() const { return *m_wallet; } From 2bc4c3eaf96f5f8490fc79280422916c5d14cde3 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Fri, 18 Jan 2019 17:05:32 -0500 Subject: [PATCH 2/2] Notify the GUI that the keypool has changed to set the receive button Whenever the keypool changes (new keys generated, new seed set, keypool runs out, etc.), notify the GUI that the keypool has changed. The receive button can then be enabled and disabled as necessary. --- src/interfaces/wallet.cpp | 4 ++++ src/interfaces/wallet.h | 4 ++++ src/qt/receivecoinsdialog.cpp | 7 ++++++- src/qt/walletmodel.cpp | 12 ++++++++++++ src/qt/walletmodel.h | 4 ++++ src/wallet/wallet.cpp | 4 ++++ src/wallet/wallet.h | 3 +++ 7 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index 8db34ed75..7481d51f1 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -488,6 +488,10 @@ public: { return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn)); } + std::unique_ptr handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) override + { + return MakeHandler(m_wallet.NotifyCanGetAddressesChanged.connect(fn)); + } std::shared_ptr m_shared_wallet; CWallet& m_wallet; diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index da60684a4..72c64ded0 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -271,6 +271,10 @@ public: //! Register handler for watchonly changed messages. using WatchOnlyChangedFn = std::function; virtual std::unique_ptr handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0; + + //! Register handler for keypool changed messages. + using CanGetAddressesChangedFn = std::function; + virtual std::unique_ptr handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) = 0; }; //! Tracking object returned by CreateTransaction and passed to CommitTransaction. diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 8942188dc..22a79a12b 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -100,8 +100,13 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model) ui->useBech32->setCheckState(Qt::Unchecked); } - // eventually disable the main receive button if private key operations are disabled + // Set the button to be enabled or disabled based on whether the wallet can give out new addresses. ui->receiveButton->setEnabled(model->canGetAddresses()); + + // Enable/disable the receive button if the wallet is now able/unable to give out new addresses. + connect(model, &WalletModel::canGetAddressesChanged, [this] { + ui->receiveButton->setEnabled(model->canGetAddresses()); + }); } } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 73fce0255..2a9144bec 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -423,6 +423,11 @@ static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly Q_ARG(bool, fHaveWatchonly)); } +static void NotifyCanGetAddressesChanged(WalletModel* walletmodel) +{ + QMetaObject::invokeMethod(walletmodel, "canGetAddressesChanged"); +} + void WalletModel::subscribeToCoreSignals() { // Connect signals to wallet @@ -432,6 +437,7 @@ void WalletModel::subscribeToCoreSignals() m_handler_transaction_changed = m_wallet->handleTransactionChanged(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2)); m_handler_show_progress = m_wallet->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2)); m_handler_watch_only_changed = m_wallet->handleWatchOnlyChanged(std::bind(NotifyWatchonlyChanged, this, std::placeholders::_1)); + m_handler_can_get_addrs_changed = m_wallet->handleCanGetAddressesChanged(boost::bind(NotifyCanGetAddressesChanged, this)); } void WalletModel::unsubscribeFromCoreSignals() @@ -443,6 +449,7 @@ void WalletModel::unsubscribeFromCoreSignals() m_handler_transaction_changed->disconnect(); m_handler_show_progress->disconnect(); m_handler_watch_only_changed->disconnect(); + m_handler_can_get_addrs_changed->disconnect(); } // WalletModel::UnlockContext implementation @@ -573,6 +580,11 @@ bool WalletModel::privateKeysDisabled() const bool WalletModel::canGetAddresses() const { + // The wallet can provide a fresh address if: + // * hdEnabled(): an HD seed is present; or + // * it is a legacy wallet, because: + // * !hdEnabled(): an HD seed is not present; and + // * !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS): private keys have not been disabled (which results in hdEnabled() == true) return m_wallet->hdEnabled() || (!m_wallet->hdEnabled() && !m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 8d7b210d2..b123befbb 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -233,6 +233,7 @@ private: std::unique_ptr m_handler_transaction_changed; std::unique_ptr m_handler_show_progress; std::unique_ptr m_handler_watch_only_changed; + std::unique_ptr m_handler_can_get_addrs_changed; interfaces::Node& m_node; bool fHaveWatchOnly; @@ -284,6 +285,9 @@ Q_SIGNALS: // Signal that wallet is about to be removed void unload(); + // Notify that there are now keys in the keypool + void canGetAddressesChanged(); + public Q_SLOTS: /* Wallet status might have changed */ void updateStatus(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 098055673..da81ee4da 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1403,6 +1403,7 @@ void CWallet::SetHDSeed(const CPubKey& seed) newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE; newHdChain.seed_id = seed.GetID(); SetHDChain(newHdChain, false); + NotifyCanGetAddressesChanged(); } void CWallet::SetHDChain(const CHDChain& chain, bool memonly) @@ -3327,6 +3328,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) 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()); } } + NotifyCanGetAddressesChanged(); return true; } @@ -3371,6 +3373,7 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe m_pool_key_to_index.erase(keypool.vchPubKey.GetID()); WalletLogPrintf("keypool reserve %d\n", nIndex); } + NotifyCanGetAddressesChanged(); return true; } @@ -3395,6 +3398,7 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey) setExternalKeyPool.insert(nIndex); } m_pool_key_to_index[pubkey.GetID()] = nIndex; + NotifyCanGetAddressesChanged(); } WalletLogPrintf("keypool return %d\n", nIndex); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 6872fbad2..e1527ea5b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1087,6 +1087,9 @@ public: /** Watch-only address added */ boost::signals2::signal NotifyWatchonlyChanged; + /** Keypool has new keys */ + boost::signals2::signal NotifyCanGetAddressesChanged; + /** Inquire whether this wallet broadcasts transactions. */ bool GetBroadcastTransactions() const { return fBroadcastTransactions; } /** Set whether this wallet broadcasts transactions. */