mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
Merge pull request #4400 from PastaPastaPasta/backport-new-wallet-pr1
Backport 14941, 15149 and 15210
This commit is contained in:
commit
4dbe320662
5
doc/release-notes-14941.md
Normal file
5
doc/release-notes-14941.md
Normal file
@ -0,0 +1,5 @@
|
||||
Miscellaneous RPC changes
|
||||
------------
|
||||
|
||||
- The `unloadwallet` RPC is now synchronous, meaning that it blocks until the
|
||||
wallet is fully unloaded.
|
@ -376,6 +376,7 @@ void PrepareShutdown()
|
||||
LogPrintf("%s: Unable to remove PID file: %s\n", __func__, e.what());
|
||||
}
|
||||
#endif
|
||||
g_wallet_init_interface.Close();
|
||||
UnregisterAllValidationInterfaces();
|
||||
GetMainSignals().UnregisterBackgroundSignalScheduler();
|
||||
GetMainSignals().UnregisterWithMempoolSignals(mempool);
|
||||
@ -397,7 +398,6 @@ void Shutdown()
|
||||
PrepareShutdown();
|
||||
}
|
||||
// Shutdown part 2: delete wallet instance
|
||||
g_wallet_init_interface.Close();
|
||||
globalVerifyHandle.reset();
|
||||
ECC_Stop();
|
||||
LogPrintf("%s: done\n", __func__);
|
||||
|
@ -73,7 +73,8 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
|
||||
|
||||
BitcoinGUI::BitcoinGUI(interfaces::Node& node, const NetworkStyle* networkStyle, QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
m_node(node)
|
||||
m_node(node),
|
||||
m_network_style(networkStyle)
|
||||
{
|
||||
GUIUtil::loadTheme(true);
|
||||
|
||||
@ -83,22 +84,12 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const NetworkStyle* networkStyle,
|
||||
move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
|
||||
}
|
||||
|
||||
QString windowTitle = tr(PACKAGE_NAME) + " - ";
|
||||
#ifdef ENABLE_WALLET
|
||||
enableWallet = WalletModel::isWalletEnabled();
|
||||
#endif // ENABLE_WALLET
|
||||
if(enableWallet)
|
||||
{
|
||||
windowTitle += tr("Wallet");
|
||||
} else {
|
||||
windowTitle += tr("Node");
|
||||
}
|
||||
QString userWindowTitle = QString::fromStdString(gArgs.GetArg("-windowtitle", ""));
|
||||
if(!userWindowTitle.isEmpty()) windowTitle += " - " + userWindowTitle;
|
||||
windowTitle += " " + networkStyle->getTitleAddText();
|
||||
QApplication::setWindowIcon(networkStyle->getTrayAndWindowIcon());
|
||||
setWindowIcon(networkStyle->getTrayAndWindowIcon());
|
||||
setWindowTitle(windowTitle);
|
||||
QApplication::setWindowIcon(m_network_style->getTrayAndWindowIcon());
|
||||
setWindowIcon(m_network_style->getTrayAndWindowIcon());
|
||||
updateWindowTitle();
|
||||
|
||||
rpcConsole = new RPCConsole(node, this, enableWallet ? Qt::Window : Qt::Widget);
|
||||
helpMessageDialog = new HelpMessageDialog(node, this, HelpMessageDialog::cmdline);
|
||||
@ -131,7 +122,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const NetworkStyle* networkStyle,
|
||||
|
||||
// Create system tray icon and notification
|
||||
if (QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
createTrayIcon(networkStyle);
|
||||
createTrayIcon();
|
||||
}
|
||||
notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
|
||||
|
||||
@ -754,10 +745,9 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
bool BitcoinGUI::addWallet(WalletModel *walletModel)
|
||||
void BitcoinGUI::addWallet(WalletModel* walletModel)
|
||||
{
|
||||
if(!walletFrame)
|
||||
return false;
|
||||
if (!walletFrame) return;
|
||||
const QString display_name = walletModel->getDisplayName();
|
||||
setWalletActionsEnabled(true);
|
||||
m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
|
||||
@ -765,12 +755,12 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel)
|
||||
m_wallet_selector_action->setVisible(true);
|
||||
}
|
||||
rpcConsole->addWallet(walletModel);
|
||||
return walletFrame->addWallet(walletModel);
|
||||
walletFrame->addWallet(walletModel);
|
||||
}
|
||||
|
||||
bool BitcoinGUI::removeWallet(WalletModel* walletModel)
|
||||
void BitcoinGUI::removeWallet(WalletModel* walletModel)
|
||||
{
|
||||
if (!walletFrame) return false;
|
||||
if (!walletFrame) return;
|
||||
int index = m_wallet_selector->findData(QVariant::fromValue(walletModel));
|
||||
m_wallet_selector->removeItem(index);
|
||||
if (m_wallet_selector->count() == 0) {
|
||||
@ -779,20 +769,21 @@ bool BitcoinGUI::removeWallet(WalletModel* walletModel)
|
||||
m_wallet_selector_action->setVisible(false);
|
||||
}
|
||||
rpcConsole->removeWallet(walletModel);
|
||||
return walletFrame->removeWallet(walletModel);
|
||||
walletFrame->removeWallet(walletModel);
|
||||
updateWindowTitle();
|
||||
}
|
||||
|
||||
bool BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
|
||||
void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
|
||||
{
|
||||
if(!walletFrame)
|
||||
return false;
|
||||
return walletFrame->setCurrentWallet(wallet_model);
|
||||
if (!walletFrame) return;
|
||||
walletFrame->setCurrentWallet(wallet_model);
|
||||
updateWindowTitle();
|
||||
}
|
||||
|
||||
bool BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
|
||||
void BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
|
||||
{
|
||||
WalletModel* wallet_model = m_wallet_selector->itemData(index).value<WalletModel*>();
|
||||
return setCurrentWallet(wallet_model);
|
||||
setCurrentWallet(wallet_model);
|
||||
}
|
||||
|
||||
void BitcoinGUI::removeAllWallets()
|
||||
@ -836,12 +827,12 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
|
||||
openAction->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle)
|
||||
void BitcoinGUI::createTrayIcon()
|
||||
{
|
||||
assert(QSystemTrayIcon::isSystemTrayAvailable());
|
||||
|
||||
trayIcon = new QSystemTrayIcon(networkStyle->getTrayAndWindowIcon(), this);
|
||||
QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + networkStyle->getTitleAddText();
|
||||
trayIcon = new QSystemTrayIcon(m_network_style->getTrayAndWindowIcon(), this);
|
||||
QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + m_network_style->getTitleAddText();
|
||||
trayIcon->setToolTip(toolTip);
|
||||
}
|
||||
|
||||
@ -1710,6 +1701,27 @@ void BitcoinGUI::updateProxyIcon()
|
||||
}
|
||||
}
|
||||
|
||||
void BitcoinGUI::updateWindowTitle()
|
||||
{
|
||||
QString window_title = tr(PACKAGE_NAME);
|
||||
#ifdef ENABLE_WALLET
|
||||
if (walletFrame) {
|
||||
WalletModel* const wallet_model = walletFrame->currentWalletModel();
|
||||
QString userWindowTitle = QString::fromStdString(gArgs.GetArg("-windowtitle", ""));
|
||||
if (!userWindowTitle.isEmpty()) {
|
||||
window_title += " - " + userWindowTitle;
|
||||
}
|
||||
if (wallet_model && !wallet_model->getWalletName().isEmpty()) {
|
||||
window_title += " - " + wallet_model->getDisplayName();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!m_network_style->getTitleAddText().isEmpty()) {
|
||||
window_title += " - " + m_network_style->getTitleAddText();
|
||||
}
|
||||
setWindowTitle(window_title);
|
||||
}
|
||||
|
||||
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
|
||||
{
|
||||
if(!clientModel)
|
||||
|
@ -80,8 +80,8 @@ public:
|
||||
The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
|
||||
functionality.
|
||||
*/
|
||||
bool addWallet(WalletModel *walletModel);
|
||||
bool removeWallet(WalletModel* walletModel);
|
||||
void addWallet(WalletModel* walletModel);
|
||||
void removeWallet(WalletModel* walletModel);
|
||||
void removeAllWallets();
|
||||
#endif // ENABLE_WALLET
|
||||
bool enableWallet = false;
|
||||
@ -197,6 +197,7 @@ private:
|
||||
|
||||
/** Timer to update custom css styling in -debug-ui mode periodically */
|
||||
QTimer* timerCustomCss = nullptr;
|
||||
const NetworkStyle* const m_network_style;
|
||||
|
||||
/** Create the main UI actions. */
|
||||
void createActions();
|
||||
@ -205,7 +206,7 @@ private:
|
||||
/** Create the toolbars */
|
||||
void createToolBars();
|
||||
/** Create system tray icon and notification */
|
||||
void createTrayIcon(const NetworkStyle *networkStyle);
|
||||
void createTrayIcon();
|
||||
/** Create system tray menu (or setup the dock menu) */
|
||||
void createIconMenu(QMenu *pmenu);
|
||||
|
||||
@ -252,8 +253,8 @@ public Q_SLOTS:
|
||||
void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr);
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
bool setCurrentWallet(WalletModel* wallet_model);
|
||||
bool setCurrentWalletBySelectorIndex(int index);
|
||||
void setCurrentWallet(WalletModel* wallet_model);
|
||||
void setCurrentWalletBySelectorIndex(int index);
|
||||
/** Set the UI status indicators based on the currently selected wallet.
|
||||
*/
|
||||
void updateWalletStatus();
|
||||
@ -282,6 +283,7 @@ public Q_SLOTS:
|
||||
private:
|
||||
/** Set the proxy-enabled icon as shown in the UI. */
|
||||
void updateProxyIcon();
|
||||
void updateWindowTitle();
|
||||
|
||||
public Q_SLOTS:
|
||||
#ifdef ENABLE_WALLET
|
||||
|
@ -247,11 +247,17 @@ void WalletFrame::usedReceivingAddresses()
|
||||
walletView->usedReceivingAddresses();
|
||||
}
|
||||
|
||||
WalletView *WalletFrame::currentWalletView()
|
||||
WalletView* WalletFrame::currentWalletView() const
|
||||
{
|
||||
return qobject_cast<WalletView*>(walletStack->currentWidget());
|
||||
}
|
||||
|
||||
WalletModel* WalletFrame::currentWalletModel() const
|
||||
{
|
||||
WalletView* wallet_view = currentWalletView();
|
||||
return wallet_view ? wallet_view->getWalletModel() : nullptr;
|
||||
}
|
||||
|
||||
void WalletFrame::outOfSyncWarningClicked()
|
||||
{
|
||||
Q_EMIT requestedSyncWarningInfo();
|
||||
|
@ -59,7 +59,8 @@ private:
|
||||
bool bOutOfSync;
|
||||
|
||||
public:
|
||||
WalletView *currentWalletView();
|
||||
WalletView* currentWalletView() const;
|
||||
WalletModel* currentWalletModel() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
/** Switch to overview (home) page */
|
||||
|
@ -402,8 +402,12 @@ void WalletInit::Stop() const
|
||||
|
||||
void WalletInit::Close() const
|
||||
{
|
||||
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
|
||||
RemoveWallet(pwallet);
|
||||
auto wallets = GetWallets();
|
||||
while (!wallets.empty()) {
|
||||
auto wallet = wallets.back();
|
||||
wallets.pop_back();
|
||||
RemoveWallet(wallet);
|
||||
UnloadWallet(std::move(wallet));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3487,16 +3487,8 @@ static UniValue unloadwallet(const JSONRPCRequest& request)
|
||||
if (!RemoveWallet(wallet)) {
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
|
||||
}
|
||||
UnregisterValidationInterface(wallet.get());
|
||||
|
||||
// The wallet can be in use so it's not possible to explicitly unload here.
|
||||
// Just notify the unload intent so that all shared pointers are released.
|
||||
// The wallet will be destroyed once the last shared pointer is released.
|
||||
wallet->NotifyUnload();
|
||||
|
||||
// There's no point in waiting for the wallet to unload.
|
||||
// At this point this method should never fail. The unloading could only
|
||||
// fail due to an unexpected error which would cause a process termination.
|
||||
UnloadWallet(std::move(wallet));
|
||||
|
||||
return NullUniValue;
|
||||
}
|
||||
|
@ -98,14 +98,52 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Mutex g_wallet_release_mutex;
|
||||
static std::condition_variable g_wallet_release_cv;
|
||||
static std::set<CWallet*> g_unloading_wallet_set;
|
||||
|
||||
// Custom deleter for shared_ptr<CWallet>.
|
||||
static void ReleaseWallet(CWallet* wallet)
|
||||
{
|
||||
// Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain
|
||||
// so that it's in sync with the current chainstate.
|
||||
wallet->WalletLogPrintf("Releasing wallet\n");
|
||||
wallet->BlockUntilSyncedToCurrentChain();
|
||||
wallet->Flush();
|
||||
UnregisterValidationInterface(wallet);
|
||||
delete wallet;
|
||||
// Wallet is now released, notify UnloadWallet, if any.
|
||||
{
|
||||
LOCK(g_wallet_release_mutex);
|
||||
if (g_unloading_wallet_set.erase(wallet) == 0) {
|
||||
// UnloadWallet was not called for this wallet, all done.
|
||||
return;
|
||||
}
|
||||
}
|
||||
g_wallet_release_cv.notify_all();
|
||||
}
|
||||
|
||||
void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
|
||||
{
|
||||
// Mark wallet for unloading.
|
||||
CWallet* pwallet = wallet.get();
|
||||
{
|
||||
LOCK(g_wallet_release_mutex);
|
||||
auto it = g_unloading_wallet_set.insert(pwallet);
|
||||
assert(it.second);
|
||||
}
|
||||
// The wallet can be in use so it's not possible to explicitly unload here.
|
||||
// Notify the unload intent so that all remaining shared pointers are
|
||||
// released.
|
||||
pwallet->NotifyUnload();
|
||||
// Time to ditch our shared_ptr and wait for ReleaseWallet call.
|
||||
wallet.reset();
|
||||
{
|
||||
WAIT_LOCK(g_wallet_release_mutex, lock);
|
||||
while (g_unloading_wallet_set.count(pwallet) == 1) {
|
||||
g_wallet_release_cv.wait(lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
|
@ -37,6 +37,13 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
//! Explicitly unload and delete the wallet.
|
||||
// Blocks the current thread after signaling the unload intent so that all
|
||||
// wallet clients release the wallet.
|
||||
// Note that, when blocking is not required, the wallet is implicitly unloaded
|
||||
// by the shared pointer deleter.
|
||||
void UnloadWallet(std::shared_ptr<CWallet>&& wallet);
|
||||
|
||||
bool AddWallet(const std::shared_ptr<CWallet>& wallet);
|
||||
bool RemoveWallet(const std::shared_ptr<CWallet>& wallet);
|
||||
bool HasWallets();
|
||||
@ -891,6 +898,8 @@ public:
|
||||
|
||||
~CWallet()
|
||||
{
|
||||
// Should not have slots connected at this point.
|
||||
assert(NotifyUnload.empty());
|
||||
delete encrypted_batch;
|
||||
encrypted_batch = nullptr;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user