LCOV - code coverage report
Current view: top level - src/wallet - load.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 118 124 95.2 %
Date: 2022-04-21 14:51:19 Functions: 8 8 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 37 46 80.4 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2009-2010 Satoshi Nakamoto
#       2                 :            : // Copyright (c) 2009-2021 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/check.h>
#      12                 :            : #include <util/string.h>
#      13                 :            : #include <util/system.h>
#      14                 :            : #include <util/translation.h>
#      15                 :            : #include <wallet/context.h>
#      16                 :            : #include <wallet/spend.h>
#      17                 :            : #include <wallet/wallet.h>
#      18                 :            : #include <wallet/walletdb.h>
#      19                 :            : 
#      20                 :            : #include <univalue.h>
#      21                 :            : 
#      22                 :            : #include <system_error>
#      23                 :            : 
#      24                 :            : namespace wallet {
#      25                 :            : bool VerifyWallets(WalletContext& context)
#      26                 :        792 : {
#      27                 :        792 :     interfaces::Chain& chain = *context.chain;
#      28                 :        792 :     ArgsManager& args = *Assert(context.args);
#      29                 :            : 
#      30         [ +  + ]:        792 :     if (args.IsArgSet("-walletdir")) {
#      31                 :         33 :         const fs::path wallet_dir{args.GetPathArg("-walletdir")};
#      32                 :         33 :         std::error_code error;
#      33                 :            :         // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
#      34                 :            :         // It also lets the fs::exists and fs::is_directory checks below pass on windows, since they return false
#      35                 :            :         // if a path has trailing slashes, and it strips trailing slashes.
#      36                 :         33 :         fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error);
#      37 [ +  + ][ -  + ]:         33 :         if (error || !fs::exists(canonical_wallet_dir)) {
#      38                 :          7 :             chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), fs::PathToString(wallet_dir)));
#      39                 :          7 :             return false;
#      40         [ +  + ]:         26 :         } else if (!fs::is_directory(canonical_wallet_dir)) {
#      41                 :          7 :             chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), fs::PathToString(wallet_dir)));
#      42                 :          7 :             return false;
#      43                 :            :         // The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
#      44         [ +  + ]:         19 :         } else if (!wallet_dir.is_absolute()) {
#      45                 :          4 :             chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), fs::PathToString(wallet_dir)));
#      46                 :          4 :             return false;
#      47                 :          4 :         }
#      48                 :         15 :         args.ForceSetArg("-walletdir", fs::PathToString(canonical_wallet_dir));
#      49                 :         15 :     }
#      50                 :            : 
#      51                 :        774 :     LogPrintf("Using wallet directory %s\n", fs::PathToString(GetWalletDir()));
#      52                 :            : 
#      53                 :        774 :     chain.initMessage(_("Verifying wallet(s)…").translated);
#      54                 :            : 
#      55                 :            :     // For backwards compatibility if an unnamed top level wallet exists in the
#      56                 :            :     // wallets directory, include it in the default list of wallets to load.
#      57         [ +  + ]:        774 :     if (!args.IsArgSet("wallet")) {
#      58                 :        613 :         DatabaseOptions options;
#      59                 :        613 :         DatabaseStatus status;
#      60                 :        613 :         ReadDatabaseArgs(args, options);
#      61                 :        613 :         bilingual_str error_string;
#      62                 :        613 :         options.require_existing = true;
#      63                 :        613 :         options.verify = false;
#      64         [ +  + ]:        613 :         if (MakeWalletDatabase("", options, status, error_string)) {
#      65                 :          1 :             util::SettingsValue wallets(util::SettingsValue::VARR);
#      66                 :          1 :             wallets.push_back(""); // Default wallet name is ""
#      67                 :            :             // Pass write=false because no need to write file and probably
#      68                 :            :             // better not to. If unnamed wallet needs to be added next startup
#      69                 :            :             // and the setting is empty, this code will just run again.
#      70                 :          1 :             chain.updateRwSetting("wallet", wallets, /* write= */ false);
#      71                 :          1 :         }
#      72                 :        613 :     }
#      73                 :            : 
#      74                 :            :     // Keep track of each wallet absolute path to detect duplicates.
#      75                 :        774 :     std::set<fs::path> wallet_paths;
#      76                 :            : 
#      77         [ +  + ]:        774 :     for (const auto& wallet : chain.getSettingsList("wallet")) {
#      78                 :        143 :         const auto& wallet_file = wallet.get_str();
#      79                 :        143 :         const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(wallet_file));
#      80                 :            : 
#      81         [ +  + ]:        143 :         if (!wallet_paths.insert(path).second) {
#      82                 :          3 :             chain.initWarning(strprintf(_("Ignoring duplicate -wallet %s."), wallet_file));
#      83                 :          3 :             continue;
#      84                 :          3 :         }
#      85                 :            : 
#      86                 :        140 :         DatabaseOptions options;
#      87                 :        140 :         DatabaseStatus status;
#      88                 :        140 :         ReadDatabaseArgs(args, options);
#      89                 :        140 :         options.require_existing = true;
#      90                 :        140 :         options.verify = true;
#      91                 :        140 :         bilingual_str error_string;
#      92         [ +  + ]:        140 :         if (!MakeWalletDatabase(wallet_file, options, status, error_string)) {
#      93         [ -  + ]:          8 :             if (status == DatabaseStatus::FAILED_NOT_FOUND) {
#      94                 :          0 :                 chain.initWarning(Untranslated(strprintf("Skipping -wallet path that doesn't exist. %s", error_string.original)));
#      95                 :          8 :             } else {
#      96                 :          8 :                 chain.initError(error_string);
#      97                 :          8 :                 return false;
#      98                 :          8 :             }
#      99                 :          8 :         }
#     100                 :        140 :     }
#     101                 :            : 
#     102                 :        766 :     return true;
#     103                 :        774 : }
#     104                 :            : 
#     105                 :            : bool LoadWallets(WalletContext& context)
#     106                 :        723 : {
#     107                 :        723 :     interfaces::Chain& chain = *context.chain;
#     108                 :        723 :     try {
#     109                 :        723 :         std::set<fs::path> wallet_paths;
#     110         [ +  + ]:        723 :         for (const auto& wallet : chain.getSettingsList("wallet")) {
#     111                 :        133 :             const auto& name = wallet.get_str();
#     112         [ +  + ]:        133 :             if (!wallet_paths.insert(fs::PathFromString(name)).second) {
#     113                 :          3 :                 continue;
#     114                 :          3 :             }
#     115                 :        130 :             DatabaseOptions options;
#     116                 :        130 :             DatabaseStatus status;
#     117                 :        130 :             ReadDatabaseArgs(*context.args, options);
#     118                 :        130 :             options.require_existing = true;
#     119                 :        130 :             options.verify = false; // No need to verify, assuming verified earlier in VerifyWallets()
#     120                 :        130 :             bilingual_str error;
#     121                 :        130 :             std::vector<bilingual_str> warnings;
#     122                 :        130 :             std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
#     123 [ -  + ][ #  # ]:        130 :             if (!database && status == DatabaseStatus::FAILED_NOT_FOUND) {
#     124                 :          0 :                 continue;
#     125                 :          0 :             }
#     126                 :        130 :             chain.initMessage(_("Loading wallet…").translated);
#     127         [ +  - ]:        130 :             std::shared_ptr<CWallet> pwallet = database ? CWallet::Create(context, name, std::move(database), options.create_flags, error, warnings) : nullptr;
#     128         [ -  + ]:        130 :             if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n")));
#     129         [ -  + ]:        130 :             if (!pwallet) {
#     130                 :          0 :                 chain.initError(error);
#     131                 :          0 :                 return false;
#     132                 :          0 :             }
#     133                 :            : 
#     134                 :        130 :             NotifyWalletLoaded(context, pwallet);
#     135                 :        130 :             AddWallet(context, pwallet);
#     136                 :        130 :         }
#     137                 :        723 :         return true;
#     138                 :        723 :     } catch (const std::runtime_error& e) {
#     139                 :          2 :         chain.initError(Untranslated(e.what()));
#     140                 :          2 :         return false;
#     141                 :          2 :     }
#     142                 :        723 : }
#     143                 :            : 
#     144                 :            : void StartWallets(WalletContext& context, CScheduler& scheduler)
#     145                 :        715 : {
#     146         [ +  + ]:        715 :     for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
#     147                 :        126 :         pwallet->postInitProcess();
#     148                 :        126 :     }
#     149                 :            : 
#     150                 :            :     // Schedule periodic wallet flushes and tx rebroadcasts
#     151         [ +  - ]:        715 :     if (context.args->GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) {
#     152                 :      21245 :         scheduler.scheduleEvery([&context] { MaybeCompactWalletDB(context); }, std::chrono::milliseconds{500});
#     153                 :        715 :     }
#     154                 :      10519 :     scheduler.scheduleEvery([&context] { MaybeResendWalletTxs(context); }, std::chrono::milliseconds{1000});
#     155                 :        715 : }
#     156                 :            : 
#     157                 :            : void FlushWallets(WalletContext& context)
#     158                 :        788 : {
#     159         [ +  + ]:        788 :     for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
#     160                 :        613 :         pwallet->Flush();
#     161                 :        613 :     }
#     162                 :        788 : }
#     163                 :            : 
#     164                 :            : void StopWallets(WalletContext& context)
#     165                 :        788 : {
#     166         [ +  + ]:        788 :     for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
#     167                 :        613 :         pwallet->Close();
#     168                 :        613 :     }
#     169                 :        788 : }
#     170                 :            : 
#     171                 :            : void UnloadWallets(WalletContext& context)
#     172                 :        808 : {
#     173                 :        808 :     auto wallets = GetWallets(context);
#     174         [ +  + ]:       1421 :     while (!wallets.empty()) {
#     175                 :        613 :         auto wallet = wallets.back();
#     176                 :        613 :         wallets.pop_back();
#     177                 :        613 :         std::vector<bilingual_str> warnings;
#     178                 :        613 :         RemoveWallet(context, wallet, /* load_on_start= */ std::nullopt, warnings);
#     179                 :        613 :         UnloadWallet(std::move(wallet));
#     180                 :        613 :     }
#     181                 :        808 : }
#     182                 :            : } // namespace wallet

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a