diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 12649ac..b6bfbba 100755 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -121,8 +121,8 @@ class CMainParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,25); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,18); base58Prefixes[SECRET_KEY] = std::vector(1,239); - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x0b)(0xd3)(0x64)(0x32).convert_to_container >(); - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x0b)(0xd3)(0xc4)(0x86).convert_to_container >(); + base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container >(); + base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); vFixedSeeds = std::vector(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main)); @@ -213,8 +213,8 @@ class CTestNetParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,85); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,18); base58Prefixes[SECRET_KEY] = std::vector(1,239); - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x0b)(0xd3)(0x64)(0x32).convert_to_container >(); - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x0b)(0xd3)(0xc4)(0x86).convert_to_container >(); + base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); + base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); vFixedSeeds = std::vector(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); @@ -302,8 +302,8 @@ class CRegTestParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,45); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,48); base58Prefixes[SECRET_KEY] = std::vector(1,50); - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x26)(0xb2)(0x17)(0x06).convert_to_container >(); - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x8b)(0x36)(0x05)(0xf1).convert_to_container >(); + base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); + base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); } void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout) diff --git a/src/init.cpp b/src/init.cpp index f2301ae..aaadf22 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -39,6 +39,7 @@ #ifdef ENABLE_WALLET #include "wallet/wallet.h" #endif +#include #include #include @@ -63,6 +64,11 @@ using namespace std; +#ifdef ENABLE_WALLET +std::string strWalletFile = GetArg("-wallet", "wallet.dat"); +int nWalletBackups = 10; +#endif + bool fFeeEstimatesInitialized = false; static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_REST_ENABLE = false; @@ -386,6 +392,7 @@ std::string HelpMessage(HelpMessageMode mode) #ifdef ENABLE_WALLET strUsage += CWallet::GetWalletHelpString(showDebug); + strUsage += HelpMessageOpt("-createwalletbackups=", _("Number of automatic wallet backups (default: 10)")); #endif #if ENABLE_ZMQ @@ -484,10 +491,10 @@ std::string HelpMessage(HelpMessageMode mode) std::string LicenseInfo() { - const std::string URL_SOURCE_CODE = ""; + const std::string URL_SOURCE_CODE = ""; const std::string URL_WEBSITE = ""; // todo: remove urls from translations on next change - return CopyrightHolders(strprintf(_("Copyright (C) %i-%i"), 2009, COPYRIGHT_YEAR) + " ") + "\n" + + return CopyrightHolders(strprintf(_("Copyright (C) %i-%i"), 2017, COPYRIGHT_YEAR) + " ") + "\n" + "\n" + strprintf(_("Please contribute if you find %s useful. " "Visit %s for further information about the software."), @@ -1104,12 +1111,79 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) int64_t nStart; - // ********************************************************* Step 5: verify wallet database integrity +// ********************************************************* Step 5: Backup wallet and verify wallet database integrity #ifdef ENABLE_WALLET if (!fDisableWallet) { + boost::filesystem::path backupDir = GetDataDir() / "backups"; + if (!boost::filesystem::exists(backupDir)) { + // Always create backup folder to not confuse the operating system's file browser + boost::filesystem::create_directories(backupDir); + } + nWalletBackups = GetArg("-createwalletbackups", 10); + nWalletBackups = std::max(0, std::min(10, nWalletBackups)); + if (nWalletBackups > 0) { + if (boost::filesystem::exists(backupDir)) { + // Create backup of the wallet + std::string dateTimeStr = DateTimeStrFormat(".%Y-%m-%d-%H-%M-%S", 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(); + if (boost::filesystem::exists(sourceFile)) { +#if BOOST_VERSION >= 158000 + 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()); + } +#else + std::ifstream src(sourceFile.string(), std::ios::binary); + std::ofstream dst(backupFile.string(), std::ios::binary); + dst << src.rdbuf(); +#endif + } + // Keep only the last 10 backups, including the new one of course + typedef std::multimap 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 for current(!) wallet sorted by last write time + boost::filesystem::path currentFile; + for (boost::filesystem::directory_iterator dir_iter(backupFolder); dir_iter != end_iter; ++dir_iter) { + // Only check regular files + if (boost::filesystem::is_regular_file(dir_iter->status())) { + currentFile = dir_iter->path().filename(); + // Only add the backups for the current wallet, e.g. wallet.dat.* + if (dir_iter->path().stem().string() == strWalletFile) { + 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 N newest ones (1 <= N <= 10) + 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()); + } + } + } + } + } if (!CWallet::Verify()) return false; - } // (!fDisableWallet) + } // (!fDisableWallet) #endif // ENABLE_WALLET // ********************************************************* Step 6: network initialization diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 847d254..766cea0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3259,6 +3259,7 @@ bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, st std::string CWallet::GetWalletHelpString(bool showDebug) { std::string strUsage = HelpMessageGroup(_("Wallet options:")); + strUsage += HelpMessageOpt("-createwalletbackups=", _("Number of automatic wallet backups (default: 10)")); strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), DEFAULT_KEYPOOL_SIZE)); strUsage += HelpMessageOpt("-fallbackfee=", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),