BSHA3  0.17.99
P2P Blockchain, based on Bitcoin
init.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2018 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.
5 
6 #include <chainparams.h>
7 #include <init.h>
8 #include <net.h>
9 #include <scheduler.h>
10 #include <outputtype.h>
11 #include <util.h>
12 #include <utilmoneystr.h>
13 #include <validation.h>
14 #include <walletinitinterface.h>
15 #include <wallet/rpcwallet.h>
16 #include <wallet/wallet.h>
17 #include <wallet/walletutil.h>
18 
20 public:
21 
23  bool HasWalletSupport() const override {return true;}
24 
26  void AddWalletOptions() const override;
27 
29  bool ParameterInteraction() const override;
30 
32  void RegisterRPC(CRPCTable &tableRPC) const override;
33 
35  // This function will perform salvage on the wallet if requested, as long as only one wallet is
36  // being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
37  bool Verify() const override;
38 
40  bool Open() const override;
41 
43  void Start(CScheduler& scheduler) const override;
44 
46  void Flush() const override;
47 
49  void Stop() const override;
50 
52  void Close() const override;
53 };
54 
56 
58 {
59  gArgs.AddArg("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE)), false, OptionsCategory::WALLET);
60  gArgs.AddArg("-avoidpartialspends", strprintf(_("Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)"), DEFAULT_AVOIDPARTIALSPENDS), false, OptionsCategory::WALLET);
61  gArgs.AddArg("-changetype", "What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)", false, OptionsCategory::WALLET);
62  gArgs.AddArg("-disablewallet", "Do not load the wallet and disable wallet RPC calls", false, OptionsCategory::WALLET);
63  gArgs.AddArg("-discardfee=<amt>", strprintf("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
64  "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",
65  CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE)), false, OptionsCategory::WALLET);
66  gArgs.AddArg("-fallbackfee=<amt>", strprintf("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)",
67  CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)), false, OptionsCategory::WALLET);
68  gArgs.AddArg("-keypool=<n>", strprintf("Set key pool size to <n> (default: %u)", DEFAULT_KEYPOOL_SIZE), false, OptionsCategory::WALLET);
69  gArgs.AddArg("-mintxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)",
70  CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)), false, OptionsCategory::WALLET);
71  gArgs.AddArg("-paytxfee=<amt>", strprintf("Fee (in %s/kB) to add to transactions you send (default: %s)",
73  gArgs.AddArg("-rescan", "Rescan the block chain for missing wallet transactions on startup", false, OptionsCategory::WALLET);
74  gArgs.AddArg("-salvagewallet", "Attempt to recover private keys from a corrupt wallet on startup", false, OptionsCategory::WALLET);
75  gArgs.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), false, OptionsCategory::WALLET);
76  gArgs.AddArg("-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), false, OptionsCategory::WALLET);
77  gArgs.AddArg("-upgradewallet", "Upgrade wallet to latest format on startup", false, OptionsCategory::WALLET);
78  gArgs.AddArg("-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>.)", false, OptionsCategory::WALLET);
79  gArgs.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), false, OptionsCategory::WALLET);
80  gArgs.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", false, OptionsCategory::WALLET);
81  gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", false, OptionsCategory::WALLET);
82  gArgs.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), false, OptionsCategory::WALLET);
83  gArgs.AddArg("-zapwallettxes=<mode>", "Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup"
84  " (1 = keep tx meta data e.g. payment request information, 2 = drop tx meta data)", false, OptionsCategory::WALLET);
85 
86  gArgs.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), true, OptionsCategory::WALLET_DEBUG_TEST);
87  gArgs.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), true, OptionsCategory::WALLET_DEBUG_TEST);
88  gArgs.AddArg("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB), true, OptionsCategory::WALLET_DEBUG_TEST);
89  gArgs.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), true, OptionsCategory::WALLET_DEBUG_TEST);
90 }
91 
93 {
94  if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
95  for (const std::string& wallet : gArgs.GetArgs("-wallet")) {
96  LogPrintf("%s: parameter interaction: -disablewallet -> ignoring -wallet=%s\n", __func__, wallet);
97  }
98 
99  return true;
100  }
101 
102  gArgs.SoftSetArg("-wallet", "");
103  const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
104 
105  if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
106  LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
107  }
108 
109  if (gArgs.GetBoolArg("-salvagewallet", false)) {
110  if (is_multiwallet) {
111  return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet"));
112  }
113  // Rewrite just private keys: rescan to find transactions
114  if (gArgs.SoftSetBoolArg("-rescan", true)) {
115  LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
116  }
117  }
118 
119  bool zapwallettxes = gArgs.GetBoolArg("-zapwallettxes", false);
120  // -zapwallettxes implies dropping the mempool on startup
121  if (zapwallettxes && gArgs.SoftSetBoolArg("-persistmempool", false)) {
122  LogPrintf("%s: parameter interaction: -zapwallettxes enabled -> setting -persistmempool=0\n", __func__);
123  }
124 
125  // -zapwallettxes implies a rescan
126  if (zapwallettxes) {
127  if (is_multiwallet) {
128  return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
129  }
130  if (gArgs.SoftSetBoolArg("-rescan", true)) {
131  LogPrintf("%s: parameter interaction: -zapwallettxes enabled -> setting -rescan=1\n", __func__);
132  }
133  }
134 
135  if (is_multiwallet) {
136  if (gArgs.GetBoolArg("-upgradewallet", false)) {
137  return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet"));
138  }
139  }
140 
141  if (gArgs.GetBoolArg("-sysperms", false))
142  return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
143  if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false))
144  return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again."));
145 
146  if (::minRelayTxFee.GetFeePerK() > HIGH_TX_FEE_PER_KB)
147  InitWarning(AmountHighWarn("-minrelaytxfee") + " " +
148  _("The wallet will avoid paying less than the minimum relay fee."));
149 
150  if (gArgs.IsArgSet("-maxtxfee"))
151  {
152  CAmount nMaxFee = 0;
153  if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee))
154  return InitError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")));
155  if (nMaxFee > HIGH_MAX_TX_FEE)
156  InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
157  maxTxFee = nMaxFee;
158  if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
159  {
160  return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
161  gArgs.GetArg("-maxtxfee", ""), ::minRelayTxFee.ToString()));
162  }
163  }
164 
165  return true;
166 }
167 
169 {
170  if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
171  return;
172  }
173 
175 }
176 
177 bool WalletInit::Verify() const
178 {
179  if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
180  return true;
181  }
182 
183  if (gArgs.IsArgSet("-walletdir")) {
184  fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
185  boost::system::error_code error;
186  // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
187  fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error);
188  if (error || !fs::exists(wallet_dir)) {
189  return InitError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string()));
190  } else if (!fs::is_directory(wallet_dir)) {
191  return InitError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
192  // The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
193  } else if (!wallet_dir.is_absolute()) {
194  return InitError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
195  }
196  gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string());
197  }
198 
199  LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
200 
201  uiInterface.InitMessage(_("Verifying wallet(s)..."));
202 
203  std::vector<std::string> wallet_files = gArgs.GetArgs("-wallet");
204 
205  // Parameter interaction code should have thrown an error if -salvagewallet
206  // was enabled with more than wallet file, so the wallet_files size check
207  // here should have no effect.
208  bool salvage_wallet = gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1;
209 
210  // Keep track of each wallet absolute path to detect duplicates.
211  std::set<fs::path> wallet_paths;
212 
213  for (const auto& wallet_file : wallet_files) {
214  fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
215 
216  if (!wallet_paths.insert(wallet_path).second) {
217  return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
218  }
219 
220  std::string error_string;
221  std::string warning_string;
222  bool verify_success = CWallet::Verify(wallet_file, salvage_wallet, error_string, warning_string);
223  if (!error_string.empty()) InitError(error_string);
224  if (!warning_string.empty()) InitWarning(warning_string);
225  if (!verify_success) return false;
226  }
227 
228  return true;
229 }
230 
231 bool WalletInit::Open() const
232 {
233  if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
234  LogPrintf("Wallet disabled!\n");
235  return true;
236  }
237 
238  for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
239  std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
240  if (!pwallet) {
241  return false;
242  }
243  AddWallet(pwallet);
244  }
245 
246  return true;
247 }
248 
249 void WalletInit::Start(CScheduler& scheduler) const
250 {
251  for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
252  pwallet->postInitProcess();
253  }
254 
255  // Run a thread to flush wallet periodically
256  scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
257 }
258 
259 void WalletInit::Flush() const
260 {
261  for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
262  pwallet->Flush(false);
263  }
264 }
265 
266 void WalletInit::Stop() const
267 {
268  for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
269  pwallet->Flush(true);
270  }
271 }
272 
273 void WalletInit::Close() const
274 {
275  for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
276  RemoveWallet(pwallet);
277  }
278 }
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: util.cpp:502
static bool Verify(std::string wallet_file, bool salvage_wallet, std::string &error_string, std::string &warning_string)
Verify wallet naming and perform salvage on the wallet if required.
Definition: wallet.cpp:3824
Bitcoin RPC command dispatcher.
Definition: server.h:143
std::vector< std::shared_ptr< CWallet > > GetWallets()
Definition: dummywallet.cpp:47
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn&#39;t already have a value.
Definition: util.cpp:558
constexpr CAmount DEFAULT_PAY_TX_FEE
-paytxfee default
Definition: wallet.h:48
#define strprintf
Definition: tinyformat.h:1066
bool AddWallet(const std::shared_ptr< CWallet > &wallet)
Definition: wallet.cpp:43
CAmount maxTxFee
Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendra...
Definition: validation.cpp:242
void AddWalletOptions() const override
Return the wallets help message.
Definition: init.cpp:57
void scheduleEvery(Function f, int64_t deltaMilliSeconds)
Definition: scheduler.cpp:126
const std::string CURRENCY_UNIT
Definition: feerate.cpp:10
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: util.cpp:542
bool HasWalletSupport() const override
Was the wallet component compiled in.
Definition: init.cpp:23
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: util.cpp:566
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn&#39;t already have a value.
Definition: util.cpp:550
static std::shared_ptr< CWallet > CreateWalletFromFile(const std::string &name, const fs::path &path, uint64_t wallet_creation_flags=0)
Definition: wallet.cpp:3875
void Close() const override
Close all wallets.
Definition: init.cpp:273
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
bool Open() const override
Load wallet databases.
Definition: init.cpp:231
CRPCTable tableRPC
Definition: server.cpp:556
CFeeRate minRelayTxFee
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) ...
Definition: validation.cpp:241
void MaybeCompactWalletDB()
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
Definition: walletdb.cpp:653
constexpr OutputType DEFAULT_ADDRESS_TYPE
Default for -addresstype.
Definition: wallet.h:101
bool ParseMoney(const std::string &str, CAmount &nRet)
void RegisterRPC(CRPCTable &tableRPC) const override
Register wallet RPCs.
Definition: init.cpp:168
std::string AmountHighWarn(const std::string &optname)
std::string FormatMoney(const CAmount &n)
Money parsing/formatting utilities.
bool Verify() const override
Responsible for reading and validating the -wallet arguments and verifying the wallet database...
Definition: init.cpp:177
void RegisterWalletRPCCommands(CRPCTable &t)
Definition: rpcwallet.cpp:4039
const std::string & FormatOutputType(OutputType type)
Definition: outputtype.cpp:35
ArgsManager gArgs
Definition: util.cpp:88
const WalletInitInterface & g_wallet_init_interface
Definition: init.cpp:55
void Stop() const override
Stop all wallets. Wallets will be flushed first.
Definition: init.cpp:266
bool InitError(const std::string &str)
Show error message.
void AddArg(const std::string &name, const std::string &help, const bool debug_only, const OptionsCategory &cat)
Add argument.
Definition: util.cpp:572
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: util.cpp:526
bool RemoveWallet(const std::shared_ptr< CWallet > &wallet)
Definition: wallet.cpp:53
void Flush() const override
Flush all wallets in preparation for shutdown.
Definition: init.cpp:259
Fee rate in satoshis per kilobyte: CAmount / kB.
Definition: feerate.h:19
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: dummywallet.cpp:37
bool error(const char *fmt, const Args &... args)
Definition: util.h:59
void Start(CScheduler &scheduler) const override
Complete startup of wallets.
Definition: init.cpp:249
std::string ToString() const
Definition: feerate.cpp:40
void InitWarning(const std::string &str)
Show warning message.
CClientUIInterface uiInterface
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: util.cpp:483
bool ParameterInteraction() const override
Wallets parameter interaction.
Definition: init.cpp:92
std::string AmountErrMsg(const char *const optname, const std::string &strValue)
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:41
std::string _(const char *psz)
Translation function.
Definition: util.h:50