Skip to content

Commit

Permalink
Merge pull request #306 from crowning-/auto-wallet-backup
Browse files Browse the repository at this point in the history
Configurable Automatic Wallet Backup
  • Loading branch information
evan82 committed Apr 13, 2015
2 parents a8d7a3f + 5a18577 commit 73b831c
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 17 deletions.
94 changes: 78 additions & 16 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ using namespace boost;
#ifdef ENABLE_WALLET
std::string strWalletFile;
CWallet* pwalletMain;
int nWalletBackups = 10;
#endif

#ifdef WIN32
Expand Down Expand Up @@ -273,21 +274,22 @@ std::string HelpMessage(HelpMessageMode hmm)

#ifdef ENABLE_WALLET
strUsage += "\n" + _("Wallet options:") + "\n";
strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n";
strUsage += " -keepass " + _("Use KeePass 2 integration using KeePassHttp plugin (default: 0)") + "\n";
strUsage += " -keepassport=<port> " + _("Connect to KeePassHttp on port <port> (default: 19455)") + "\n";
strUsage += " -keepasskey=<key> " + _("KeePassHttp key for AES encrypted communication with KeePass") + "\n";
strUsage += " -keepassid=<name> " + _("KeePassHttp id for the established association") + "\n";
strUsage += " -keepassname=<name> " + _("Name to construct url for KeePass entry that stores the wallet passphrase") + "\n";
strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 1000)") + "\n";
strUsage += " -paytxfee=<amt> " + _("Fee per kB to add to transactions you send") + "\n";
strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n";
strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n";
strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n";
strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n";
strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n";
strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
strUsage += " -zapwallettxes " + _("Clear list of wallet transactions (diagnostic tool; implies -rescan)") + "\n";
strUsage += " -createwalletbackups=<n> " + _("Number of automatic wallet backups (default: 10)") + "\n";
strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n";
strUsage += " -keepass " + _("Use KeePass 2 integration using KeePassHttp plugin (default: 0)") + "\n";
strUsage += " -keepassport=<port> " + _("Connect to KeePassHttp on port <port> (default: 19455)") + "\n";
strUsage += " -keepasskey=<key> " + _("KeePassHttp key for AES encrypted communication with KeePass") + "\n";
strUsage += " -keepassid=<name> " + _("KeePassHttp id for the established association") + "\n";
strUsage += " -keepassname=<name> " + _("Name to construct url for KeePass entry that stores the wallet passphrase") + "\n";
strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 1000)") + "\n";
strUsage += " -paytxfee=<amt> " + _("Fee per kB to add to transactions you send") + "\n";
strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n";
strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n";
strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n";
strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n";
strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n";
strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
strUsage += " -zapwallettxes " + _("Clear list of wallet transactions (diagnostic tool; implies -rescan)") + "\n";
#endif

strUsage += "\n" + _("Debugging/Testing options:") + "\n";
Expand Down Expand Up @@ -711,9 +713,69 @@ bool AppInit2(boost::thread_group& threadGroup)

int64_t nStart;

// ********************************************************* Step 5: verify wallet database integrity
// ********************************************************* Step 5: Backup wallet and verify wallet database integrity
#ifdef ENABLE_WALLET
if (!fDisableWallet) {

filesystem::path backupDir = GetDataDir() / "backups";
if (!filesystem::exists(backupDir))
{
// Always create backup folder to not confuse the operating system's file browser
filesystem::create_directories(backupDir);
}
nWalletBackups = GetArg("-createwalletbackups", 10);
nWalletBackups = std::max(0, std::min(10, nWalletBackups));
if(nWalletBackups > 0)
{
if (filesystem::exists(backupDir))
{
// Create backup of the wallet
std::string dateTimeStr = DateTimeStrFormat(".%Y-%m-%d-%H.%M", GetTime());
std::string backupPathStr = backupDir.string();
backupPathStr += "/" + strWalletFile;
std::string sourcePathStr = GetDataDir().string();
sourcePathStr += "/" + strWalletFile;
boost::filesystem::path sourceFile = sourcePathStr;
boost::filesystem::path backupFile = backupPathStr + dateTimeStr;
sourceFile.make_preferred();
backupFile.make_preferred();
try {
boost::filesystem::copy_file(sourceFile, backupFile);
LogPrintf("Creating backup of %s -> %s\n", sourceFile, backupFile);
} catch(boost::filesystem::filesystem_error &error) {
LogPrintf("Failed to create backup %s\n", error.what());
}
// Keep only the last 10 backups, including the new one of course
typedef std::multimap<std::time_t, boost::filesystem::path> folder_set_t;
folder_set_t folder_set;
boost::filesystem::directory_iterator end_iter;
boost::filesystem::path backupFolder = backupDir.string();
backupFolder.make_preferred();
// Build map of backup files sorted by last write time
for (boost::filesystem::directory_iterator dir_iter(backupFolder); dir_iter != end_iter; ++dir_iter)
{
if ( boost::filesystem::is_regular_file(dir_iter->status()))
folder_set.insert(folder_set_t::value_type(boost::filesystem::last_write_time(dir_iter->path()), *dir_iter));
}
// Loop backward through backup files and keep the 10 newest ones
int counter = 0;
BOOST_REVERSE_FOREACH(PAIRTYPE(const std::time_t, boost::filesystem::path) file, folder_set)
{
counter++;
if (counter > nWalletBackups)
{
// More than nWalletBackups backups: delete oldest one(s)
try {
boost::filesystem::remove(file.second);
LogPrintf("Old backup deleted: %s\n", file.second);
} catch(boost::filesystem::filesystem_error &error) {
LogPrintf("Failed to delete backup %s\n", error.what());
}
}
}
}
}

LogPrintf("Using wallet %s\n", strWalletFile);
uiInterface.InitMessage(_("Verifying wallet..."));

Expand Down
Empty file modified src/init.h
100644 → 100755
Empty file.
3 changes: 2 additions & 1 deletion src/qt/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ RES_ICONS = \
res/icons/drkblue_editpaste.png \
res/icons/drkblue_address-book.png \
res/icons/drkblue_editcopy.png \
res/icons/drkblue_remove.png
res/icons/drkblue_remove.png \
res/icons/browse.png


BITCOIN_QT_CPP = \
Expand Down
5 changes: 5 additions & 0 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(showConsole()));
connect(openNetworkAction, SIGNAL(triggered()), rpcConsole, SLOT(showNetwork()));
connect(openConfEditorAction, SIGNAL(triggered()), rpcConsole, SLOT(showConfEditor()));
connect(showBackupsAction, SIGNAL(triggered()), rpcConsole, SLOT(showBackups()));


// prevents an oben debug window from becoming stuck/unusable on client shutdown
Expand Down Expand Up @@ -330,6 +331,8 @@ void BitcoinGUI::createActions(bool fIsTestnet)
openNetworkAction->setStatusTip(tr("Show network monitor"));
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);
showBackupsAction->setStatusTip(tr("Show automatically created wallet backups"));

usedSendingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("&Sending addresses..."), this);
usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
Expand Down Expand Up @@ -408,6 +411,7 @@ void BitcoinGUI::createMenuBar()
tools->addAction(openRPCConsoleAction);
tools->addAction(openNetworkAction);
tools->addAction(openConfEditorAction);
tools->addAction(showBackupsAction);
}

QMenu *help = appMenuBar->addMenu(tr("&Help"));
Expand Down Expand Up @@ -570,6 +574,7 @@ void BitcoinGUI::createTrayIconMenu()
trayIconMenu->addAction(openRPCConsoleAction);
trayIconMenu->addAction(openNetworkAction);
trayIconMenu->addAction(openConfEditorAction);
trayIconMenu->addAction(showBackupsAction);
#ifndef Q_OS_MAC // This is built-in on Mac
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
Expand Down
1 change: 1 addition & 0 deletions src/qt/bitcoingui.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class BitcoinGUI : public QMainWindow
QAction *openRPCConsoleAction;
QAction *openNetworkAction;
QAction *openConfEditorAction;
QAction *showBackupsAction;
QAction *openAction;
QAction *showHelpMessageAction;

Expand Down
1 change: 1 addition & 0 deletions src/qt/dash.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<file alias="drkblue_address-book">res/icons/drkblue_address-book.png</file>
<file alias="drkblue_editcopy">res/icons/drkblue_editcopy.png</file>
<file alias="drkblue_remove">res/icons/drkblue_remove.png</file>
<file alias="browse">res/icons/browse.png</file>
</qresource>
<qresource prefix="/css">
<file alias="drkblue">res/css/drkblue.css</file>
Expand Down
9 changes: 9 additions & 0 deletions src/qt/guiutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,15 @@ void openConfigfile()
QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathConfig)));
}

void showBackups()
{
boost::filesystem::path pathBackups = GetDataDir() / "backups";

/* Open folder with default browser */
if (boost::filesystem::exists(pathBackups))
QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathBackups)));
}

ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent) :
QObject(parent), size_threshold(size_threshold)
{
Expand Down
3 changes: 3 additions & 0 deletions src/qt/guiutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ namespace GUIUtil

// Open dash.conf
void openConfigfile();

// Browse backup folder
void showBackups();

/** Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text
representation if needed. This assures that Qt can word-wrap long tooltip messages.
Expand Down
Binary file added src/qt/res/icons/browse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/qt/rpcconsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,8 @@ void RPCConsole::showConfEditor()
{
GUIUtil::openConfigfile();
}

void RPCConsole::showBackups()
{
GUIUtil::showBackups();
}
2 changes: 2 additions & 0 deletions src/qt/rpcconsole.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public slots:
void showNetwork();
/** Open external (default) editor with dash.conf */
void showConfEditor();
/** Show folder with wallet backups in default browser */
void showBackups();

signals:
// For RPC command executor
Expand Down

0 comments on commit 73b831c

Please sign in to comment.