Use MakeUnique<Db>(...)
[bitcoinplatinum.git] / src / wallet / init.cpp
blob6b5d4cc6688454ec47eb15995e2d0877f60e0708
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #include "wallet/init.h"
8 #include "net.h"
9 #include "util.h"
10 #include "utilmoneystr.h"
11 #include "validation.h"
12 #include "wallet/wallet.h"
13 #include "wallet/rpcwallet.h"
15 std::string GetWalletHelpString(bool showDebug)
17 std::string strUsage = HelpMessageGroup(_("Wallet options:"));
18 strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
19 strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
20 strUsage += HelpMessageOpt("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),
21 CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)));
22 strUsage += HelpMessageOpt("-discardfee=<amt>", strprintf(_("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
23 "Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target"),
24 CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE)));
25 strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
26 CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
27 strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
28 CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
29 strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions on startup"));
30 strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet on startup"));
31 strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
32 strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
33 strUsage += HelpMessageOpt("-walletrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (default: %u)"), DEFAULT_WALLET_RBF));
34 strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup"));
35 strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
36 strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST));
37 strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
38 strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
39 " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
41 if (showDebug)
43 strUsage += HelpMessageGroup(_("Wallet debugging/testing options:"));
45 strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
46 strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET));
47 strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB));
48 strUsage += HelpMessageOpt("-walletrejectlongchains", strprintf(_("Wallet will not create transactions that violate mempool chain limits (default: %u)"), DEFAULT_WALLET_REJECT_LONG_CHAINS));
51 return strUsage;
54 bool WalletParameterInteraction()
56 if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
57 for (const std::string& wallet : gArgs.GetArgs("-wallet")) {
58 LogPrintf("%s: parameter interaction: -disablewallet -> ignoring -wallet=%s\n", __func__, wallet);
61 return true;
64 gArgs.SoftSetArg("-wallet", DEFAULT_WALLET_DAT);
65 const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
67 if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
68 LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
71 if (gArgs.GetBoolArg("-salvagewallet", false)) {
72 if (is_multiwallet) {
73 return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet"));
75 // Rewrite just private keys: rescan to find transactions
76 if (gArgs.SoftSetBoolArg("-rescan", true)) {
77 LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
81 int zapwallettxes = gArgs.GetArg("-zapwallettxes", 0);
82 // -zapwallettxes implies dropping the mempool on startup
83 if (zapwallettxes != 0 && gArgs.SoftSetBoolArg("-persistmempool", false)) {
84 LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -persistmempool=0\n", __func__, zapwallettxes);
87 // -zapwallettxes implies a rescan
88 if (zapwallettxes != 0) {
89 if (is_multiwallet) {
90 return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
92 if (gArgs.SoftSetBoolArg("-rescan", true)) {
93 LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -rescan=1\n", __func__, zapwallettxes);
97 if (is_multiwallet) {
98 if (gArgs.GetBoolArg("-upgradewallet", false)) {
99 return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet"));
103 if (gArgs.GetBoolArg("-sysperms", false))
104 return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
105 if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false))
106 return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again."));
108 if (::minRelayTxFee.GetFeePerK() > HIGH_TX_FEE_PER_KB)
109 InitWarning(AmountHighWarn("-minrelaytxfee") + " " +
110 _("The wallet will avoid paying less than the minimum relay fee."));
112 if (gArgs.IsArgSet("-mintxfee"))
114 CAmount n = 0;
115 if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n)
116 return InitError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
117 if (n > HIGH_TX_FEE_PER_KB)
118 InitWarning(AmountHighWarn("-mintxfee") + " " +
119 _("This is the minimum transaction fee you pay on every transaction."));
120 CWallet::minTxFee = CFeeRate(n);
122 if (gArgs.IsArgSet("-fallbackfee"))
124 CAmount nFeePerK = 0;
125 if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK))
126 return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", "")));
127 if (nFeePerK > HIGH_TX_FEE_PER_KB)
128 InitWarning(AmountHighWarn("-fallbackfee") + " " +
129 _("This is the transaction fee you may pay when fee estimates are not available."));
130 CWallet::fallbackFee = CFeeRate(nFeePerK);
132 if (gArgs.IsArgSet("-discardfee"))
134 CAmount nFeePerK = 0;
135 if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK))
136 return InitError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", "")));
137 if (nFeePerK > HIGH_TX_FEE_PER_KB)
138 InitWarning(AmountHighWarn("-discardfee") + " " +
139 _("This is the transaction fee you may discard if change is smaller than dust at this level"));
140 CWallet::m_discard_rate = CFeeRate(nFeePerK);
142 if (gArgs.IsArgSet("-paytxfee"))
144 CAmount nFeePerK = 0;
145 if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK))
146 return InitError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
147 if (nFeePerK > HIGH_TX_FEE_PER_KB)
148 InitWarning(AmountHighWarn("-paytxfee") + " " +
149 _("This is the transaction fee you will pay if you send a transaction."));
151 payTxFee = CFeeRate(nFeePerK, 1000);
152 if (payTxFee < ::minRelayTxFee)
154 return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
155 gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString()));
158 if (gArgs.IsArgSet("-maxtxfee"))
160 CAmount nMaxFee = 0;
161 if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee))
162 return InitError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")));
163 if (nMaxFee > HIGH_MAX_TX_FEE)
164 InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
165 maxTxFee = nMaxFee;
166 if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
168 return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
169 gArgs.GetArg("-maxtxfee", ""), ::minRelayTxFee.ToString()));
172 nTxConfirmTarget = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
173 bSpendZeroConfChange = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
174 fWalletRbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
176 return true;
179 void RegisterWalletRPC(CRPCTable &t)
181 if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
182 return;
185 RegisterWalletRPCCommands(t);
188 bool VerifyWallets()
190 if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
191 return true;
194 uiInterface.InitMessage(_("Verifying wallet(s)..."));
196 // Keep track of each wallet absolute path to detect duplicates.
197 std::set<fs::path> wallet_paths;
199 for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
200 if (boost::filesystem::path(walletFile).filename() != walletFile) {
201 return InitError(strprintf(_("Error loading wallet %s. -wallet parameter must only specify a filename (not a path)."), walletFile));
204 if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) {
205 return InitError(strprintf(_("Error loading wallet %s. Invalid characters in -wallet filename."), walletFile));
208 fs::path wallet_path = fs::absolute(walletFile, GetDataDir());
210 if (fs::exists(wallet_path) && (!fs::is_regular_file(wallet_path) || fs::is_symlink(wallet_path))) {
211 return InitError(strprintf(_("Error loading wallet %s. -wallet filename must be a regular file."), walletFile));
214 if (!wallet_paths.insert(wallet_path).second) {
215 return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), walletFile));
218 std::string strError;
219 if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) {
220 return InitError(strError);
223 if (gArgs.GetBoolArg("-salvagewallet", false)) {
224 // Recover readable keypairs:
225 CWallet dummyWallet;
226 std::string backup_filename;
227 if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) {
228 return false;
232 std::string strWarning;
233 bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError);
234 if (!strWarning.empty()) {
235 InitWarning(strWarning);
237 if (!dbV) {
238 InitError(strError);
239 return false;
243 return true;
246 bool OpenWallets()
248 if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
249 LogPrintf("Wallet disabled!\n");
250 return true;
253 for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
254 CWallet * const pwallet = CWallet::CreateWalletFromFile(walletFile);
255 if (!pwallet) {
256 return false;
258 vpwallets.push_back(pwallet);
261 return true;
264 void StartWallets(CScheduler& scheduler) {
265 for (CWalletRef pwallet : vpwallets) {
266 pwallet->postInitProcess(scheduler);
270 void FlushWallets() {
271 for (CWalletRef pwallet : vpwallets) {
272 pwallet->Flush(false);
276 void StopWallets() {
277 for (CWalletRef pwallet : vpwallets) {
278 pwallet->Flush(true);
282 void CloseWallets() {
283 for (CWalletRef pwallet : vpwallets) {
284 delete pwallet;
286 vpwallets.clear();