LCOV - code coverage report
Current view: top level - src/wallet - init.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 98 139 70.5 %
Date: 2025-02-23 09:33:43 Functions: 4 4 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2017 The Bitcoin Core developers
       3             : // Copyright (c) 2021 The PIVX Core developers
       4             : // Distributed under the MIT software license, see the accompanying
       5             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       6             : 
       7             : #include "wallet/init.h"
       8             : 
       9             : #include "guiinterfaceutil.h"
      10             : #include "net.h"
      11             : #include "util/system.h"
      12             : #include "utilmoneystr.h"
      13             : #include "validation.h"
      14             : #include "wallet/wallet.h"
      15             : #include "wallet/walletutil.h"
      16             : 
      17           1 : std::string GetWalletHelpString(bool showDebug)
      18             : {
      19           1 :     std::string strUsage = HelpMessageGroup("Wallet options:");
      20           4 :     strUsage += HelpMessageOpt("-createwalletbackups=<n>", strprintf("Number of automatic wallet backups (default: %d)", DEFAULT_CREATEWALLETBACKUPS));
      21           3 :     strUsage += HelpMessageOpt("-disablewallet", strprintf("Do not load the wallet and disable wallet RPC calls (default: %u)", DEFAULT_DISABLE_WALLET));
      22           3 :     strUsage += HelpMessageOpt("-keypool=<n>", strprintf("Set key pool size to <n> (default: %u)", DEFAULT_KEYPOOL_SIZE));
      23           3 :     strUsage += HelpMessageOpt("-legacywallet", "On first run, create a legacy wallet instead of a HD wallet");
      24           4 :     strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf("Maximum total fees to use in a single wallet transaction, setting too low may abort large transactions (default: %s)", FormatMoney(maxTxFee)));
      25           4 :     strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf("Fees (in %s/Kb) smaller than this are considered zero fee for transaction creation (default: %s)", CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK())));
      26           4 :     strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf("Fee (in %s/kB) to add to transactions you send (default: %s)", CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
      27           3 :     strUsage += HelpMessageOpt("-rescan", "Rescan the block chain for missing wallet transactions on startup");
      28           3 :     strUsage += HelpMessageOpt("-salvagewallet", "Attempt to recover private keys from a corrupt wallet file on startup");
      29           4 :     strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE));
      30           4 :     strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)", 1));
      31           3 :     strUsage += HelpMessageOpt("-upgradewallet", "Upgrade wallet to latest format on startup");
      32           3 :     strUsage += HelpMessageOpt("-wallet=<path>", "Specify wallet database path. Can be specified multiple times to load multiple wallets. Path is interpreted relative to <walletdir> if it is not absolute, and will be created if it does not exist (as a directory containing a wallet.dat file and log files). For backwards compatibility this will also accept names of existing data files in <walletdir>.)");
      33           4 :     strUsage += HelpMessageOpt("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)");
      34           4 :     strUsage += HelpMessageOpt("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)");
      35           3 :     strUsage += HelpMessageOpt("-zapwallettxes=<mode>", "Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup"
      36           1 :         "(1 = keep tx meta data e.g. payment request information, 2 = drop tx meta data)");
      37           3 :     strUsage += HelpMessageGroup("Mining/Staking options:");
      38           4 :     strUsage += HelpMessageOpt("-coldstaking=<n>", strprintf("Enable cold staking functionality (0-1, default: %u). Disabled if staking=0", DEFAULT_COLDSTAKING));
      39           3 :     strUsage += HelpMessageOpt("-gen", strprintf("Generate coins (default: %u)", DEFAULT_GENERATE));
      40           4 :     strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)", DEFAULT_GENERATE_PROCLIMIT));
      41           5 :     strUsage += HelpMessageOpt("-minstakesplit=<amt>", strprintf("Minimum positive amount (in PIV) allowed by GUI and RPC for the stake split threshold (default: %s)", FormatMoney(DEFAULT_MIN_STAKE_SPLIT_THRESHOLD)));
      42           3 :     strUsage += HelpMessageOpt("-staking=<n>", strprintf("Enable staking functionality (0-1, default: %u)", DEFAULT_STAKING));
      43           1 :     if (showDebug) {
      44           0 :         strUsage += HelpMessageGroup("Wallet debugging/testing options:");
      45           0 :         strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
      46           0 :         strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET));
      47           0 :         strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB));
      48             :     }
      49             : 
      50           1 :     return strUsage;
      51             : }
      52             : 
      53         386 : bool WalletParameterInteraction()
      54             : {
      55         386 :     if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
      56             :         return true;
      57             :     }
      58             : 
      59         375 :     if (gArgs.GetBoolArg("-sysperms", false)) {
      60           0 :         return UIError(strprintf(_("%s is not allowed in combination with enabled wallet functionality"), "-sysperms"));
      61             :     }
      62             : 
      63         750 :     gArgs.SoftSetArg("-wallet", "");
      64         375 :     const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
      65             : 
      66         375 :     if (gArgs.GetBoolArg("-salvagewallet", false)) {
      67           2 :         if (is_multiwallet) {
      68           6 :             return UIError(strprintf(_("%s is only allowed with a single wallet file"), "-salvagewallet"));
      69             :         }
      70             :         // Rewrite just private keys: rescan to find transactions
      71           0 :         if (gArgs.SoftSetBoolArg("-rescan", true)) {
      72           0 :             LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
      73             :         }
      74             :     }
      75             : 
      76         373 :     bool zapwallettxes = gArgs.GetBoolArg("-zapwallettxes", false);
      77             :     // -zapwallettxes implies dropping the mempool on startup
      78         381 :     if (zapwallettxes && gArgs.SoftSetBoolArg("-persistmempool", false)) {
      79           8 :         LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -persistmempool=0\n", __func__, zapwallettxes);
      80             :     }
      81             : 
      82             :     // -zapwallettxes implies a rescan
      83         373 :     if (zapwallettxes) {
      84           8 :         if (is_multiwallet) {
      85           9 :             return UIError(strprintf(_("%s is only allowed with a single wallet file"), "-zapwallettxes"));
      86             :         }
      87           5 :         if (gArgs.SoftSetBoolArg("-rescan", true)) {
      88           5 :             LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__);
      89             :         }
      90             :     }
      91             : 
      92         370 :     if (is_multiwallet) {
      93           8 :         if (gArgs.GetBoolArg("-upgradewallet", false)) {
      94           6 :             return UIError(strprintf(_("%s is only allowed with a single wallet file"), "-upgradewallet"));
      95             :         }
      96             :     }
      97             : 
      98         368 :     if (gArgs.IsArgSet("-mintxfee")) {
      99           0 :         CAmount n = 0;
     100           0 :         if (ParseMoney(gArgs.GetArg("-mintxfee", ""), n) && n > 0)
     101           0 :             CWallet::minTxFee = CFeeRate(n);
     102             :         else
     103           0 :             return UIError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
     104             :     }
     105         368 :     if (gArgs.IsArgSet("-paytxfee")) {
     106           0 :         CAmount nFeePerK = 0;
     107           0 :         if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK))
     108           0 :             return UIError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
     109           0 :         if (nFeePerK > nHighTransactionFeeWarning)
     110           0 :             UIWarning(strprintf(_("Warning: %s is set very high! This is the transaction fee you will pay if you send a transaction."), "-paytxfee"));
     111           0 :         payTxFee = CFeeRate(nFeePerK, 1000);
     112           0 :         if (payTxFee < ::minRelayTxFee) {
     113           0 :             return UIError(strprintf(_("Invalid amount for %s: '%s' (must be at least %s)"), "-paytxfee",
     114           0 :                                        gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString()));
     115             :         }
     116             :     }
     117         368 :     if (gArgs.IsArgSet("-maxtxfee")) {
     118           0 :         CAmount nMaxFee = 0;
     119           0 :         if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee))
     120           0 :             return UIError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")));
     121           0 :         if (nMaxFee > nHighTransactionMaxFeeWarning)
     122           0 :             UIWarning(strprintf(_("Warning: %s is set very high! Fees this large could be paid on a single transaction."), "-maxtxfee"));
     123           0 :         maxTxFee = nMaxFee;
     124           0 :         if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee) {
     125           0 :             return UIError(strprintf(_("Invalid amount for %s: '%s' (must be at least the minimum relay fee of %s to prevent stuck transactions)"),
     126           0 :                                        "-maxtxfee", gArgs.GetArg("-maxtxfee", ""), ::minRelayTxFee.ToString()));
     127             :         }
     128             :     }
     129         368 :     if (gArgs.IsArgSet("-minstakesplit")) {
     130           0 :         CAmount n = 0;
     131           0 :         if (ParseMoney(gArgs.GetArg("-minstakesplit", ""), n) && n > 0)
     132           0 :             CWallet::minStakeSplitThreshold = n;
     133             :         else
     134           0 :             return UIError(AmountErrMsg("minstakesplit", gArgs.GetArg("-minstakesplit", "")));
     135             :     }
     136         368 :     nTxConfirmTarget = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
     137         736 :     bSpendZeroConfChange = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
     138         368 :     bdisableSystemnotifications = gArgs.GetBoolArg("-disablesystemnotifications", false);
     139             : 
     140         368 :     return true;
     141             : }
     142             : 
     143         376 : bool WalletVerify()
     144             : {
     145         376 :     if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
     146             :         return true;
     147             :     }
     148             : 
     149         365 :     if (gArgs.IsArgSet("-walletdir")) {
     150          27 :         fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
     151          11 :         if (!fs::exists(wallet_dir)) {
     152           6 :             return UIError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string()));
     153           7 :         } else if (!fs::is_directory(wallet_dir)) {
     154           6 :             return UIError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
     155           5 :         } else if (!wallet_dir.is_absolute()) {
     156           3 :             return UIError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
     157             :         }
     158             :     }
     159             : 
     160         360 :     LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
     161             : 
     162         360 :     uiInterface.InitMessage(_("Verifying wallet(s)..."));
     163             : 
     164             :     // Keep track of each wallet absolute path to detect duplicates.
     165         735 :     std::set<fs::path> wallet_paths;
     166             : 
     167         735 :     for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
     168         754 :         auto opRes = VerifyWalletPath(walletFile);
     169         380 :         if (!opRes) return UIError(opRes.getError());
     170             : 
     171        1133 :         fs::path wallet_path = fs::absolute(walletFile, GetWalletDir());
     172         378 :         if (!wallet_paths.insert(wallet_path).second) {
     173           4 :             return UIError(strprintf(_("Error loading wallet %s. Duplicate %s filename specified."), walletFile, "-wallet"));
     174             :         }
     175             : 
     176         752 :         std::string strError;
     177         377 :         if (!WalletBatch::VerifyEnvironment(wallet_path, strError)) {
     178           5 :             return UIError(strError);
     179             :         }
     180             : 
     181         374 :         if (gArgs.GetBoolArg("-salvagewallet", false)) {
     182             :             // Recover readable keypairs:
     183           1 :             CWallet dummyWallet("dummy", WalletDatabase::CreateDummy());
     184           0 :             std::string backup_filename;
     185             :             // Even if we don't use this lock in this function, we want to preserve
     186             :             // lock order in LoadToWallet if query of chain state is needed to know
     187             :             // tx status. If lock can't be taken, tx confirmation status may be not
     188             :             // reliable.
     189           0 :             LOCK(cs_main);
     190           0 :             if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
     191           0 :                 return false;
     192             :             }
     193             :         }
     194             : 
     195         748 :         std::string strWarning;
     196         374 :         bool dbV = WalletBatch::VerifyDatabaseFile(wallet_path, strWarning, strError);
     197         374 :         if (!strWarning.empty()) {
     198           0 :             UIWarning(strWarning);
     199             :         }
     200         374 :         if (!dbV) {
     201           2 :             return UIError(strError);
     202             :         }
     203             :     }
     204             : 
     205         355 :     return true;
     206             : }
     207             : 
     208         356 : bool InitLoadWallet()
     209             : {
     210         356 :     if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
     211          11 :         LogPrintf("Wallet disabled!\n");
     212          11 :         return true;
     213             :     }
     214             : 
     215         707 :     for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
     216             :         // create/load wallet
     217        1092 :         CWallet * const pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
     218         362 :         if (!pwallet) {
     219           0 :             return false;
     220             :         }
     221             : 
     222             :         // add to wallets in use
     223         362 :         vpwallets.emplace_back(pwallet);
     224             :     }
     225             : 
     226             :     // automatic backup
     227             :     // do this after loading all wallets, so unique fileids are checked properly
     228         705 :     for (CWallet* pwallet: vpwallets) {
     229         722 :         std::string strWarning, strError;
     230         361 :         if (!AutoBackupWallet(*pwallet, strWarning, strError)) {
     231          74 :             if (!strWarning.empty()) {
     232           0 :                 UIWarning(strprintf("%s: %s", pwallet->GetName(), strWarning));
     233             :             }
     234          74 :             if (!strError.empty()) {
     235           0 :                 return UIError(strprintf("%s: %s", pwallet->GetName(), strError));
     236             :             }
     237             :         }
     238             :     }
     239             : 
     240         344 :     return true;
     241             : }

Generated by: LCOV version 1.14