Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2020 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 <wallet/load.h> 7 : 8 : #include <fs.h> 9 : #include <interfaces/chain.h> 10 : #include <scheduler.h> 11 : #include <util/string.h> 12 : #include <util/system.h> 13 : #include <util/translation.h> 14 : #include <wallet/wallet.h> 15 : #include <wallet/walletdb.h> 16 : 17 : #include <univalue.h> 18 : 19 528 : bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files) 20 : { 21 530 : if (gArgs.IsArgSet("-walletdir")) { 22 24 : fs::path wallet_dir = gArgs.GetArg("-walletdir", ""); 23 24 : boost::system::error_code error; 24 : // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory 25 24 : fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error); 26 24 : if (error || !fs::exists(wallet_dir)) { 27 5 : chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string())); 28 5 : return false; 29 19 : } else if (!fs::is_directory(wallet_dir)) { 30 5 : chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string())); 31 5 : return false; 32 : // The canonical path transforms relative paths into absolute ones, so we check the non-canonical version 33 14 : } else if (!wallet_dir.is_absolute()) { 34 3 : chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string())); 35 3 : return false; 36 : } 37 11 : gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string()); 38 24 : } 39 : 40 515 : LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); 41 : 42 515 : chain.initMessage(_("Verifying wallet(s)...").translated); 43 : 44 : // Keep track of each wallet absolute path to detect duplicates. 45 515 : std::set<fs::path> wallet_paths; 46 : 47 788 : for (const auto& wallet_file : wallet_files) { 48 273 : const fs::path path = fs::absolute(wallet_file, GetWalletDir()); 49 : 50 273 : if (!wallet_paths.insert(path).second) { 51 2 : chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file)); 52 2 : return false; 53 : } 54 : 55 271 : DatabaseOptions options; 56 271 : DatabaseStatus status; 57 271 : options.verify = true; 58 271 : bilingual_str error_string; 59 271 : if (!MakeWalletDatabase(wallet_file, options, status, error_string)) { 60 5 : chain.initError(error_string); 61 5 : return false; 62 : } 63 273 : } 64 : 65 506 : return true; 66 530 : } 67 : 68 492 : bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files) 69 : { 70 : try { 71 744 : for (const std::string& name : wallet_files) { 72 252 : DatabaseOptions options; 73 252 : DatabaseStatus status; 74 252 : options.verify = false; // No need to verify, assuming verified earlier in VerifyWallets() 75 252 : bilingual_str error; 76 252 : std::vector<bilingual_str> warnings; 77 252 : std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error); 78 252 : std::shared_ptr<CWallet> pwallet = database ? CWallet::Create(chain, name, std::move(database), options.create_flags, error, warnings) : nullptr; 79 250 : if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n"))); 80 250 : if (!pwallet) { 81 0 : chain.initError(error); 82 0 : return false; 83 : } 84 250 : AddWallet(pwallet); 85 252 : } 86 490 : return true; 87 2 : } catch (const std::runtime_error& e) { 88 2 : chain.initError(Untranslated(e.what())); 89 : return false; 90 2 : } 91 494 : } 92 : 93 487 : void StartWallets(CScheduler& scheduler, const ArgsManager& args) 94 : { 95 732 : for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) { 96 245 : pwallet->postInitProcess(); 97 : } 98 : 99 : // Schedule periodic wallet flushes and tx rebroadcasts 100 487 : if (args.GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) { 101 487 : scheduler.scheduleEvery(MaybeCompactWalletDB, std::chrono::milliseconds{500}); 102 487 : } 103 487 : scheduler.scheduleEvery(MaybeResendWalletTxs, std::chrono::milliseconds{1000}); 104 487 : } 105 : 106 524 : void FlushWallets() 107 : { 108 1128 : for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) { 109 604 : pwallet->Flush(); 110 : } 111 524 : } 112 : 113 524 : void StopWallets() 114 : { 115 1128 : for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) { 116 604 : pwallet->Close(); 117 : } 118 524 : } 119 : 120 1000 : void UnloadWallets() 121 : { 122 1000 : auto wallets = GetWallets(); 123 1604 : while (!wallets.empty()) { 124 604 : auto wallet = wallets.back(); 125 604 : wallets.pop_back(); 126 604 : std::vector<bilingual_str> warnings; 127 604 : RemoveWallet(wallet, nullopt, warnings); 128 604 : UnloadWallet(std::move(wallet)); 129 604 : } 130 1000 : }