Merge pull request #342 from crowning-/Wallet_Repair

Wallet Repair Buttons
This commit is contained in:
UdjinM6 2015-05-29 11:26:03 +03:00
commit 04f9fb043f
20 changed files with 429 additions and 7 deletions

24
src/init.cpp Executable file → Normal file
View File

@ -58,6 +58,7 @@ CWallet* pwalletMain = NULL;
int nWalletBackups = 10;
#endif
bool fFeeEstimatesInitialized = false;
bool fRestartRequested = false; // true: restart false: shutdown
#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
@ -143,8 +144,10 @@ public:
static CCoinsViewDB *pcoinsdbview = NULL;
static CCoinsViewErrorCatcher *pcoinscatcher = NULL;
void Shutdown()
/** Preparing steps before shutting down or restarting the wallet */
void PrepareShutdown()
{
fRestartRequested = true; // Needed when we restart the wallet
LogPrintf("%s: In progress...\n", __func__);
static CCriticalSection cs_Shutdown;
TRY_LOCK(cs_Shutdown, lockShutdown);
@ -201,6 +204,25 @@ void Shutdown()
boost::filesystem::remove(GetPidFile());
#endif
UnregisterAllValidationInterfaces();
}
/**
* Shutdown is split into 2 parts:
* Part 1: shut down everything but the main wallet instance (done in PrepareShutdown() )
* Part 2: delete wallet instance
*
* In case of a restart PrepareShutdown() was already called before, but this method here gets
* called implicitly when the parent object is deleted. In this case we have to skip the
* PrepareShutdown() part because it was already executed and just delete the wallet instance.
*/
void Shutdown()
{
// Shutdown part 1: prepare shutdown
if(!fRestartRequested){
PrepareShutdown();
}
// Shutdown part 2: delete wallet instance
#ifdef ENABLE_WALLET
delete pwalletMain;
pwalletMain = NULL;

1
src/init.h Executable file → Normal file
View File

@ -20,6 +20,7 @@ extern CWallet* pwalletMain;
void StartShutdown();
bool ShutdownRequested();
void Shutdown();
void PrepareShutdown();
bool AppInit2(boost::thread_group& threadGroup);
/** The help message mode determines what help message to show */

View File

@ -1739,11 +1739,13 @@ public:
}
instance_of_cnetcleanup;
void CExplicitNetCleanup::callCleanup()
{
// Explicit call to destructor of CNetCleanup because it's not implicitly called
// when the wallet is restarted from within the wallet itself.
CNetCleanup *tmp = new CNetCleanup();
delete tmp; // Stroustrup's gonna kill me for that
}
void RelayTransaction(const CTransaction& tx)
{

View File

@ -672,7 +672,11 @@ public:
static uint64_t GetTotalBytesSent();
};
class CExplicitNetCleanup
{
public:
static void callCleanup();
};
class CTransaction;
void RelayTransaction(const CTransaction& tx);

View File

@ -213,14 +213,19 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent) :
statusBar()->addWidget(progressBar);
statusBar()->addPermanentWidget(frameBlocks);
// Jump directly to tabs in RPC-console
connect(openInfoAction, SIGNAL(triggered()), rpcConsole, SLOT(showInfo()));
connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(showConsole()));
connect(openNetworkAction, SIGNAL(triggered()), rpcConsole, SLOT(showNetwork()));
connect(openPeersAction, SIGNAL(triggered()), rpcConsole, SLOT(showPeers()));
connect(openRepairAction, SIGNAL(triggered()), rpcConsole, SLOT(showRepair()));
connect(openConfEditorAction, SIGNAL(triggered()), rpcConsole, SLOT(showConfEditor()));
connect(showBackupsAction, SIGNAL(triggered()), rpcConsole, SLOT(showBackups()));
connect(labelConnectionsIcon, SIGNAL(clicked()), rpcConsole, SLOT(showPeers()));
// Get restart command-line parameters and handle restart
connect(rpcConsole, SIGNAL(handleRestart(QStringList)), this, SLOT(handleRestart(QStringList)));
// prevents an open debug window from becoming stuck/unusable on client shutdown
connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
@ -352,6 +357,8 @@ void BitcoinGUI::createActions(const NetworkStyle *networkStyle)
openNetworkAction->setStatusTip(tr("Show network monitor"));
openPeersAction = new QAction(QIcon(":/icons/connect_4"), tr("&Peers list"), this);
openPeersAction->setStatusTip(tr("Show peers info"));
openRepairAction = new QAction(QIcon(":/icons/options"), tr("Wallet &Repair"), this);
openRepairAction->setStatusTip(tr("Show wallet repair options"));
openConfEditorAction = new QAction(QIcon(":/icons/edit"), tr("Open &Configuration File"), this);
openConfEditorAction->setStatusTip(tr("Open configuration file"));
showBackupsAction = new QAction(QIcon(":/icons/browse"), tr("Show Automatic &Backups"), this);
@ -435,6 +442,7 @@ void BitcoinGUI::createMenuBar()
tools->addAction(openRPCConsoleAction);
tools->addAction(openNetworkAction);
tools->addAction(openPeersAction);
tools->addAction(openRepairAction);
tools->addSeparator();
tools->addAction(openConfEditorAction);
tools->addAction(showBackupsAction);
@ -602,6 +610,7 @@ void BitcoinGUI::createTrayIconMenu()
trayIconMenu->addAction(openRPCConsoleAction);
trayIconMenu->addAction(openNetworkAction);
trayIconMenu->addAction(openPeersAction);
trayIconMenu->addAction(openRepairAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(openConfEditorAction);
trayIconMenu->addAction(showBackupsAction);
@ -1109,6 +1118,13 @@ void BitcoinGUI::unsubscribeFromCoreSignals()
uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
}
/** Get restart command-line parameters and request restart */
void BitcoinGUI::handleRestart(QStringList args)
{
if (!ShutdownRequested())
emit requestedRestart(args);
}
UnitDisplayStatusBarControl::UnitDisplayStatusBarControl() :
optionsModel(0),
menu(0)

View File

@ -109,6 +109,7 @@ private:
QAction *openRPCConsoleAction;
QAction *openNetworkAction;
QAction *openPeersAction;
QAction *openRepairAction;
QAction *openConfEditorAction;
QAction *showBackupsAction;
QAction *openAction;
@ -145,12 +146,16 @@ private:
signals:
/** Signal raised when a URI was entered or dragged to the GUI */
void receivedURI(const QString &uri);
/** Restart handling */
void requestedRestart(QStringList args);
public slots:
/** Set number of connections shown in the UI */
void setNumConnections(int count);
/** Set number of blocks shown in the UI */
void setNumBlocks(int count);
/** Get restart command-line parameters and request restart */
void handleRestart(QStringList args);
/** Notify the user of an event from the core network or transaction handling code.
@param[in] title the message box / notification title

0
src/qt/coincontroldialog.cpp Executable file → Normal file
View File

View File

@ -13,6 +13,7 @@
#include "guiconstants.h"
#include "guiutil.h"
#include "intro.h"
#include "net.h"
#include "networkstyle.h"
#include "optionsmodel.h"
#include "splashscreen.h"
@ -45,6 +46,7 @@
#include <QLibraryInfo>
#include <QLocale>
#include <QMessageBox>
#include <QProcess>
#include <QSettings>
#include <QThread>
#include <QTimer>
@ -173,6 +175,7 @@ public:
public slots:
void initialize();
void shutdown();
void restart(QStringList args);
signals:
void initializeResult(int retval);
@ -224,6 +227,7 @@ public slots:
signals:
void requestedInitialize();
void requestedRestart(QStringList args);
void requestedShutdown();
void stopThread();
void splashFinished(QWidget *window);
@ -277,6 +281,27 @@ void BitcoinCore::initialize()
}
}
void BitcoinCore::restart(QStringList args)
{
try
{
qDebug() << __func__ << ": Running Restart in thread";
threadGroup.interrupt_all();
threadGroup.join_all();
PrepareShutdown();
qDebug() << __func__ << ": Shutdown finished";
emit shutdownResult(1);
CExplicitNetCleanup::callCleanup();
QProcess::startDetached(QApplication::applicationFilePath(), args);
qDebug() << __func__ << ": Restart initiated...";
QCoreApplication::quit();
} catch (std::exception& e) {
handleRunawayException(&e);
} catch (...) {
handleRunawayException(NULL);
}
}
void BitcoinCore::shutdown()
{
try
@ -375,6 +400,7 @@ void BitcoinApplication::startThread()
connect(executor, SIGNAL(runawayException(QString)), this, SLOT(handleRunawayException(QString)));
connect(this, SIGNAL(requestedInitialize()), executor, SLOT(initialize()));
connect(this, SIGNAL(requestedShutdown()), executor, SLOT(shutdown()));
connect(window, SIGNAL(requestedRestart(QStringList)), executor, SLOT(restart(QStringList)));
/* make sure executor object is deleted in its own thread */
connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
connect(this, SIGNAL(stopThread()), coreThread, SLOT(quit()));

View File

@ -1064,6 +1064,257 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_repair">
<attribute name="title">
<string>&amp;Wallet Repair</string>
</attribute>
<widget class="QPushButton" name="btn_salvagewallet">
<property name="geometry">
<rect>
<x>10</x>
<y>90</y>
<width>221</width>
<height>23</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>180</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Salvage wallet</string>
</property>
</widget>
<widget class="QPushButton" name="btn_rescan">
<property name="geometry">
<rect>
<x>10</x>
<y>140</y>
<width>221</width>
<height>23</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>180</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Rescan blockchain files</string>
</property>
</widget>
<widget class="QPushButton" name="btn_zapwallettxes1">
<property name="geometry">
<rect>
<x>10</x>
<y>190</y>
<width>221</width>
<height>23</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>180</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Recover transactions 1</string>
</property>
</widget>
<widget class="QPushButton" name="btn_zapwallettxes2">
<property name="geometry">
<rect>
<x>10</x>
<y>240</y>
<width>221</width>
<height>23</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>180</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Recover transactions 2</string>
</property>
</widget>
<widget class="QPushButton" name="btn_upgradewallet">
<property name="geometry">
<rect>
<x>10</x>
<y>290</y>
<width>221</width>
<height>23</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>180</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Upgrade wallet format</string>
</property>
</widget>
<widget class="QLabel" name="label_repair_helptext">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>711</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>The buttons below will restart the wallet with command-line options to repair the wallet, fix issues with corrupt blockhain files or missing/obsolete transactions.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="label_repair_salvage">
<property name="geometry">
<rect>
<x>250</x>
<y>80</y>
<width>471</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>-salvagewallet: Attempt to recover private keys from a corrupt wallet.dat.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="label_repair_rescan">
<property name="geometry">
<rect>
<x>250</x>
<y>129</y>
<width>471</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>-rescan: Rescan the block chain for missing wallet transactions.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="label_repair_zap1">
<property name="geometry">
<rect>
<x>250</x>
<y>179</y>
<width>471</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>-zapwallettxes=1: Recover transactions from blockchain (keep meta-data, e.g. account owner).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="label_repair_zap2">
<property name="geometry">
<rect>
<x>250</x>
<y>229</y>
<width>471</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>-zapwallettxes=2: Recover transactions from blockchain (drop meta-data).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="label_repair_upgrade">
<property name="geometry">
<rect>
<x>250</x>
<y>279</y>
<width>471</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>-upgradewallet: Upgrade wallet to latest format on startup. (Note: this is NOT an update of the wallet itself!)</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="label_repair_header">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>711</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Wallet repair options.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton" name="btn_reindex">
<property name="geometry">
<rect>
<x>10</x>
<y>340</y>
<width>221</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Rebuild index</string>
</property>
</widget>
<widget class="QLabel" name="label_repair_reindex">
<property name="geometry">
<rect>
<x>250</x>
<y>330</y>
<width>471</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>-reindex: Rebuild block chain index from current blk000??.dat files.</string>
</property>
</widget>
</widget>
</widget>
</item>
</layout>

0
src/qt/guiutil.cpp Executable file → Normal file
View File

0
src/qt/guiutil.h Executable file → Normal file
View File

0
src/qt/optionsdialog.cpp Executable file → Normal file
View File

0
src/qt/optionsmodel.cpp Executable file → Normal file
View File

0
src/qt/optionsmodel.h Executable file → Normal file
View File

0
src/qt/overviewpage.cpp Executable file → Normal file
View File

80
src/qt/rpcconsole.cpp Executable file → Normal file
View File

@ -42,6 +42,14 @@ const QSize ICON_SIZE(24, 24);
const int INITIAL_TRAFFIC_GRAPH_MINS = 30;
// Repair parameters
const QString SALVAGEWALLET("-salvagewallet");
const QString RESCAN("-rescan");
const QString ZAPTXES1("-zapwallettxes=1");
const QString ZAPTXES2("-zapwallettxes=2");
const QString UPGRADEWALLET("-upgradewallet");
const QString REINDEX("-reindex");
const struct {
const char *url;
const char *source;
@ -220,6 +228,14 @@ RPCConsole::RPCConsole(QWidget *parent) :
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear()));
// Wallet Repair Buttons
connect(ui->btn_salvagewallet, SIGNAL(clicked()), this, SLOT(walletSalvage()));
connect(ui->btn_rescan, SIGNAL(clicked()), this, SLOT(walletRescan()));
connect(ui->btn_zapwallettxes1, SIGNAL(clicked()), this, SLOT(walletZaptxes1()));
connect(ui->btn_zapwallettxes2, SIGNAL(clicked()), this, SLOT(walletZaptxes2()));
connect(ui->btn_upgradewallet, SIGNAL(clicked()), this, SLOT(walletUpgrade()));
connect(ui->btn_reindex, SIGNAL(clicked()), this, SLOT(walletReindex()));
// set library version labels
ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));
@ -336,6 +352,64 @@ static QString categoryClass(int category)
}
}
/** Restart wallet with "-salvagewallet" */
void RPCConsole::walletSalvage()
{
buildParameterlist(SALVAGEWALLET);
}
/** Restart wallet with "-rescan" */
void RPCConsole::walletRescan()
{
buildParameterlist(RESCAN);
}
/** Restart wallet with "-zapwallettxes=1" */
void RPCConsole::walletZaptxes1()
{
buildParameterlist(ZAPTXES1);
}
/** Restart wallet with "-zapwallettxes=2" */
void RPCConsole::walletZaptxes2()
{
buildParameterlist(ZAPTXES2);
}
/** Restart wallet with "-upgradewallet" */
void RPCConsole::walletUpgrade()
{
buildParameterlist(UPGRADEWALLET);
}
/** Restart wallet with "-reindex" */
void RPCConsole::walletReindex()
{
buildParameterlist(REINDEX);
}
/** Build command-line parameter list for restart */
void RPCConsole::buildParameterlist(QString arg)
{
// Get command-line arguments and remove the application name
QStringList args = QApplication::arguments();
args.removeFirst();
// Remove existing repair-options
args.removeAll(SALVAGEWALLET);
args.removeAll(RESCAN);
args.removeAll(ZAPTXES1);
args.removeAll(ZAPTXES2);
args.removeAll(UPGRADEWALLET);
args.removeAll(REINDEX);
// Append repair parameter to command line.
args.append(arg);
// Send command-line arguments to BitcoinGUI::handleRestart()
emit handleRestart(args);
}
void RPCConsole::clear()
{
ui->messagesWidget->clear();
@ -550,6 +624,12 @@ void RPCConsole::showPeers()
show();
}
void RPCConsole::showRepair()
{
ui->tabWidget->setCurrentIndex(4);
show();
}
void RPCConsole::showConfEditor()
{
GUIUtil::openConfigfile();

15
src/qt/rpcconsole.h Executable file → Normal file
View File

@ -59,6 +59,15 @@ private slots:
public slots:
void clear();
/** Wallet repair options */
void walletSalvage();
void walletRescan();
void walletZaptxes1();
void walletZaptxes2();
void walletUpgrade();
void walletReindex();
void reject();
void message(int category, const QString &message, bool html = false);
/** Set number of connections shown in the UI */
@ -79,6 +88,8 @@ public slots:
void showNetwork();
/** Switch to peers tab and show */
void showPeers();
/** Switch to wallet-repair tab and show */
void showRepair();
/** Open external (default) editor with dash.conf */
void showConfEditor();
/** Handle selection of peer in peers list */
@ -92,11 +103,15 @@ signals:
// For RPC command executor
void stopExecutor();
void cmdRequest(const QString &command);
/** Get restart command-line parameters and handle restart */
void handleRestart(QStringList args);
private:
static QString FormatBytes(quint64 bytes);
void startExecutor();
void setTrafficGraphRange(int mins);
/** Build parameter list for restart */
void buildParameterlist(QString arg);
/** show detailed information on ui about selected node */
void updateNodeDetail(const CNodeCombinedStats *stats);

0
src/qt/transactiondescdialog.cpp Executable file → Normal file
View File

0
src/qt/transactionview.cpp Executable file → Normal file
View File

0
src/util.cpp Executable file → Normal file
View File