wallet: let Listwalletdir do not iterate through our blocksdata. #19419

pull Saibato wants to merge 2 commits into bitcoin:master from Saibato:wallet_351 changing 2 files +44 −18
  1. Saibato commented at 7:12 am on June 30, 2020: contributor

    Fix: While fiddling with wallets, I noticed that if datadir == walltetsdir an unsynced node can become quite unresponsive.

    if no “wallets” dir is in datadir ( i.e. exiting old node ) we would have iterate trough our own node files to find wallets, that consumes time and could cause an unresponsive node.

  2. fanquake added the label Wallet on Jun 30, 2020
  3. Saibato force-pushed on Jun 30, 2020
  4. Saibato force-pushed on Jun 30, 2020
  5. Saibato renamed this:
    wallet: Listwallets do not iterate trough our blocksdata.
    wallet: Listwalletdir do not iterate trough our blocksdata.
    on Jun 30, 2020
  6. DrahtBot commented at 1:00 pm on June 30, 2020: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #20125 (rpc, wallet: Expose database format in getwalletinfo by promag)
    • #19933 (wallet: bugfix; if datadir has a trailing ‘/’ listwalletdir would strip lead char of walletname by Saibato)
    • #19502 (Bugfix: Wallet: Soft-fail exceptions within ListWalletDir file checks by luke-jr)
    • #19077 (wallet: Add sqlite as an alternative wallet database and use it for new descriptor wallets by achow101)
    • #18095 (Fix crashes and infinite loop in ListWalletDir() by uhliksk)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  7. promag commented at 9:40 am on July 1, 2020: member

    No strong opinion regarding excluding some paths. Current patch needs to be updated (format) and maybe change implementation to use a list of ignore/exclude paths.

    This can improve GUI by reducing freezes but it’s not the right fix for that. When ListWalletDir is triggered from the GUI, it should be called on a background thread. Alternatively we could consider caching ListWalletDir result and invalidate it when wallets are created or loaded.

  8. Saibato commented at 12:22 pm on July 1, 2020: contributor

    No strong opinion regarding excluding some paths. Current patch needs to be updated (format) and maybe change implementation to use a list of ignore/exclude paths.

    This can improve GUI by reducing freezes but it’s not the right fix for that. When ListWalletDir is triggered from the GUI, it should be called on a background thread. Alternatively we could consider caching ListWalletDir result and invalidate it when wallets are created or loaded.

    yup, ugly quick fix and background thread seams reasonable.. but fix proves the point and lets be honest why should we waste time and risk locks, when traverse trough known node dir?.. . also other GUI freezes should be tackled. Before moon scale there is a long list of things in my backlog, that need to be fixed before bam.. . There might be soon real users who use the gui, and lets be real, gui is bitcoin for them.

  9. Saibato renamed this:
    wallet: Listwalletdir do not iterate trough our blocksdata.
    [WIP} wallet: Listwalletdir do not iterate trough our blocksdata.
    on Jul 1, 2020
  10. Saibato renamed this:
    [WIP} wallet: Listwalletdir do not iterate trough our blocksdata.
    [WIP] wallet: Listwalletdir do not iterate trough our blocksdata.
    on Jul 1, 2020
  11. Saibato force-pushed on Jul 1, 2020
  12. Saibato force-pushed on Jul 1, 2020
  13. Saibato force-pushed on Jul 1, 2020
  14. Saibato force-pushed on Jul 1, 2020
  15. Saibato force-pushed on Jul 1, 2020
  16. Saibato force-pushed on Jul 1, 2020
  17. in src/wallet/walletutil.cpp:66 in 3d69e4ccae outdated
    59@@ -60,33 +60,69 @@ std::vector<fs::path> ListWalletDir()
    60     const size_t offset = wallet_dir.string().size() + 1;
    61     std::vector<fs::path> paths;
    62     boost::system::error_code ec;
    63+    fs::path sub_path = GetDataDir();
    64+
    65+    bool we_have_wallets_dir = (wallet_dir != sub_path);
    66+    const fs::path fblocks = GetBlocksDir();
    


    promag commented at 9:40 pm on July 1, 2020:
    Instead of multiple variables, you can declare something like const std::vector ignore_paths{ GetBlocksDir(), sub_path / "testnet3", ... } and then compare against this.

    Saibato commented at 1:39 am on July 2, 2020:
    yup :+1: , btw strange how long those bare strings survived refactor, still no global #define BLOCKS_DIR or TESTNET_STR etc.
  18. Saibato force-pushed on Jul 2, 2020
  19. Saibato force-pushed on Jul 2, 2020
  20. Saibato renamed this:
    [WIP] wallet: Listwalletdir do not iterate trough our blocksdata.
    wallet: let Listwalletdir do not iterate trough our blocksdata.
    on Jul 2, 2020
  21. in src/wallet/walletutil.cpp:85 in 4aa7bc58d4 outdated
    84-        // Get wallet path relative to walletdir by removing walletdir from the wallet path.
    85-        // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
    86-        const fs::path path = it->path().string().substr(offset);
    87+        // We dont want to iterate trough those special node dirs
    88+        if (it->status().type() == fs::directory_file) {
    89+            skip_path = false;
    


    Sjors commented at 6:23 pm on July 9, 2020:

    better to define skip_path here

    Note to other reviewers, the enum file_type: https://www.boost.org/doc/libs/1_66_0/libs/filesystem/doc/reference.html#Enum-file_type

  22. in src/wallet/walletutil.cpp:88 in 4aa7bc58d4 outdated
    87+        // We dont want to iterate trough those special node dirs
    88+        if (it->status().type() == fs::directory_file) {
    89+            skip_path = false;
    90+            for(const auto& fpath: ignore_paths) {
    91+                if (!skip_path && it->path().string().find(fpath.string()) == 0) {
    92+                    skip_path = true;
    


    Sjors commented at 6:26 pm on July 9, 2020:

    could use break; so you don’t need to check !skip_path && (and in fact, don’t need it at all)

    You can also do it.disable_recursion_pending(); here


    Saibato commented at 9:51 am on July 13, 2020:

    (and in fact, don’t need it at all)

    hmm… If we allow wallets in those dir yes, but i would choose to touch the dir’s not at all, Please view fixup I will post before i squash. I guess we will need the skip But sure about that we need some vote. :+1:

  23. in src/wallet/walletutil.cpp:95 in 4aa7bc58d4 outdated
    94+            }
    95+            if (skip_path) {
    96+                it.disable_recursion_pending();
    97+                continue;
    98+            }
    99+        } else it.disable_recursion_pending();
    


    Sjors commented at 6:28 pm on July 9, 2020:

    nit: just use brackets and newline

    Also, I think we should follow symlinks? symlink_file


    luke-jr commented at 6:45 pm on July 12, 2020:
    Following symlinks could create an infinite loop.
  24. Sjors commented at 6:39 pm on July 9, 2020: member

    Concept ACK

    This seems orthogonal to using a background thread. We shouldn’t be looking for wallets inside the blocks and chainstate dir even in the background.

  25. in src/wallet/walletutil.cpp:87 in 4aa7bc58d4 outdated
    86-        const fs::path path = it->path().string().substr(offset);
    87+        // We dont want to iterate trough those special node dirs
    88+        if (it->status().type() == fs::directory_file) {
    89+            skip_path = false;
    90+            for(const auto& fpath: ignore_paths) {
    91+                if (!skip_path && it->path().string().find(fpath.string()) == 0) {
    


    luke-jr commented at 6:48 pm on July 12, 2020:
    Since we’re using exact paths in ignore_paths, can’t we use an exact match? (And then ignore_paths can become an unordered_set and just use .count here…)
  26. in src/wallet/walletutil.cpp:75 in 4aa7bc58d4 outdated
    70+                                        blocks_dir,
    71+                                        data_dir / "testnet3",
    72+                                        data_dir / "regtest",
    73+                                        data_dir / "chainstate",
    74+                                        data_dir / "database",
    75+                                        data_dir / "indexes",
    


    luke-jr commented at 6:49 pm on July 12, 2020:
    Suggest alphabetising.

    luke-jr commented at 6:52 pm on July 12, 2020:
    Consider adding “blktree” and “coins” (see files.md)

    luke-jr commented at 3:58 pm on July 13, 2020:
    Maybe also the default blocks dir too

    Saibato commented at 4:31 pm on July 13, 2020:
    const std::vector<fs::path> ignore_paths = {
                                        blocks_dir,
                                        data_dir / "blktree",
  27. in src/wallet/walletutil.cpp:100 in 4aa7bc58d4 outdated
    100 
    101         if (it->status().type() == fs::directory_file && IsBerkeleyBtree(it->path() / "wallet.dat")) {
    102             // Found a directory which contains wallet.dat btree file, add it as a wallet.
    103-            paths.emplace_back(path);
    104+            // Get wallet path relative to walletdir by removing walletdir from the wallet path.
    105+            // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
    


    luke-jr commented at 6:56 pm on July 12, 2020:
    Or hopefully std::filesystem::path::lexically_relative (C++17) :)
  28. in src/wallet/walletutil.cpp:94 in 4aa7bc58d4 outdated
    93+                }
    94+            }
    95+            if (skip_path) {
    96+                it.disable_recursion_pending();
    97+                continue;
    98+            }
    


    luke-jr commented at 6:59 pm on July 12, 2020:
    0            if (ignore_paths.count(it->path()) {
    1                it.disable_recursion_pending();
    2                continue;
    3            }
    

    Saibato commented at 1:39 pm on July 13, 2020:
    :+1: Though I choose
    if (std::count(ignore_paths.begin(), ignore_paths.end(), it->path())) { not sure ignore_paths has a count?

    luke-jr commented at 3:59 pm on July 13, 2020:
    It will once changed to an unordered_set as suggested
  29. Saibato force-pushed on Jul 13, 2020
  30. meshcollider commented at 9:47 pm on August 13, 2020: contributor
    Concept ACK, looks good to me
  31. achow101 commented at 4:41 pm on August 14, 2020: member
    Concept ACK, please squash your commits.
  32. luke-jr referenced this in commit f6a9ae14f0 on Aug 15, 2020
  33. luke-jr referenced this in commit aaadd1b6a6 on Aug 15, 2020
  34. Saibato force-pushed on Aug 15, 2020
  35. Saibato commented at 12:37 pm on August 15, 2020: contributor
  36. in src/wallet/walletutil.cpp:88 in caa418440d outdated
    101-                // opened in a shared database environment for backwards compatibility.
    102-                // Add it to the list of available wallets.
    103-                paths.emplace_back(path);
    104+        // We dont want to iterate trough those special node dirs
    105+        if (std::count(ignore_paths.begin(), ignore_paths.end(), it->path())) {
    106+            it.disable_recursion_pending();
    


    luke-jr commented at 3:50 am on August 18, 2020:
    disable_recursion_pending is a new name introduced in Boost 1.72. We support much older. Renaming this to no_push (the old name) should just work.

    Saibato commented at 9:35 am on August 21, 2020:

    How about?

    Suggestion:

     0diff --git a/src/fs.h b/src/fs.h
     1index dfbecc18e..390c38790 100644
     2--- a/src/fs.h
     3+++ b/src/fs.h
     4@@ -17,6 +17,10 @@
     5 /** Filesystem operations and types */
     6 namespace fs = boost::filesystem;
     7 
     8+#ifndef NAMESPACE_BOOST
     9+#define NAMESPACE_BOOST
    10+#endif
    11+
    12 /** Bridge operations to C stdio */
    13 namespace fsbridge {
    14     FILE *fopen(const fs::path& p, const char *mode);
    15diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
    16index a1387111e..806818a36 100644
    17--- a/src/wallet/walletutil.cpp
    18+++ b/src/wallet/walletutil.cpp
    19@@ -85,7 +85,13 @@ std::vector<fs::path> ListWalletDir()
    20 
    21         // We dont want to iterate trough those special node dirs
    22         if (std::count(ignore_paths.begin(), ignore_paths.end(), it->path())) {
    23-            it.disable_recursion_pending();
    24+            #ifdef NAMESPACE_BOOST
    25+            // BOOST iterator
    26+                    it.no_push();
    27+            #else
    28+            // We have >= c++17
    29+                    it.disable_recursion_pending();
    30+            #endif
    31             continue;
    32         }
    33 
    
  37. hebasto commented at 11:35 am on October 4, 2020: member
    Concept ACK.
  38. in src/wallet/walletutil.cpp:78 in caa418440d outdated
    72+                                        data_dir / "chainstate",
    73+                                        data_dir / "coins",
    74+                                        data_dir / "database",
    75+                                        data_dir / "indexes",
    76+                                        data_dir / "regtest",
    77+                                        data_dir / "testnet3"
    


    hebasto commented at 1:13 pm on October 4, 2020:
    Please add “signet”.
  39. in src/wallet/walletutil.cpp:68 in caa418440d outdated
    63     const size_t offset = wallet_dir.string().size() + 1;
    64     std::vector<fs::path> paths;
    65     boost::system::error_code ec;
    66 
    67+    // Here we place the top level dirs we want to skip in case walletdir is datadir or blocksdir
    68+    // Those directory's are referenced in doc/files.md
    


    hebasto commented at 1:40 pm on October 4, 2020:

    nit:

    0    // Those directories are referenced in doc/files.md
    
  40. in src/wallet/walletutil.cpp:86 in caa418440d outdated
     99-                // Found top-level btree file not called wallet.dat. Current bitcoin
    100-                // software will never create these files but will allow them to be
    101-                // opened in a shared database environment for backwards compatibility.
    102-                // Add it to the list of available wallets.
    103-                paths.emplace_back(path);
    104+        // We dont want to iterate trough those special node dirs
    


    hebasto commented at 1:42 pm on October 4, 2020:

    nit:

    0        // We don't want to iterate through those special node dirs
    
  41. in src/wallet/walletutil.cpp:112 in caa418440d outdated
    124+                    // opened in a shared database environment for backwards compatibility.
    125+                    // Add it to the list of available wallets.
    126+                    paths.emplace_back(it->path().filename());
    127+                }
    128             }
    129+        } catch (const std::exception& e) {
    


    hebasto commented at 2:04 pm on October 4, 2020:
    I personally prefer “throwing” versions of the Boost.Filesystem API. But I don’t think that combining “throwing” and “non-throwing” versions of the Boost.Filesystem API in the same function is a good design.

    Saibato commented at 10:54 am on October 8, 2020:
    with catch boost::exception and dynamic_cast<std.exception i run with a recursive path in an non catched
    EXCEPTION: N5boost10filesystem16filesystem_errorE so unless u have a hint, i leave it that way, for now?
  42. wallet: let ListWalletDir do not iterate trough our blocksdata.
    When WalletDir == DataDir we would have iterate trough our own node files
    to find wallets, that consumes time and could cause an unresponsive node.
    da6eb3c2f8
  43. Saibato force-pushed on Oct 8, 2020
  44. Saibato commented at 10:59 am on October 8, 2020: contributor
  45. Saibato renamed this:
    wallet: let Listwalletdir do not iterate trough our blocksdata.
    wallet: let Listwalletdir do not iterate through our blocksdata.
    on Oct 8, 2020
  46. in src/wallet/walletutil.cpp:88 in da6eb3c2f8 outdated
    101-                // software will never create these files but will allow them to be
    102-                // opened in a shared database environment for backwards compatibility.
    103-                // Add it to the list of available wallets.
    104-                paths.emplace_back(path);
    105+        // We don't want to iterate through those special node dirs
    106+        if (std::count(ignore_paths.begin(), ignore_paths.end(), it->path())) {
    


    hebasto commented at 3:15 am on October 11, 2020:
    nit: std::find could return earlier.

    Saibato commented at 12:18 pm on October 11, 2020:

    yup. no insist here from my side, but nit too if “not” const time could that sidechannel reveal where the wallet is or else?

    Btw> since u review here and in #18095, 18095 does fix some problems, but not the wallet of death, could we transfer attention of reviewers to this here and fix some bugs fast in one sweep, before adding there new ones? I must admit my PR headlines look often a bit harmless and just like minor nits, but when I way in and insist, the hut is burning. just saying .


    hebasto commented at 1:38 pm on October 11, 2020:
    I don’t think that std::count guaranties const time to prevent sidechannel reveal where the wallet is or else. But I’m not an expert in this field. Feel free to mark this comment as resolved.

    Saibato commented at 2:24 pm on October 11, 2020:
    Ok, then i resolve this here and fix the header. thx for review.
  47. hebasto changes_requested
  48. hebasto commented at 3:18 am on October 11, 2020: member

    Approach ACK da6eb3c2f8ed5c8e2a5acb878a1abcb9d6f1c02b.

    Mind adding #include <algorithm> in separate header group?

  49. add #include <algorithm> to src/wallet/walletutil.h
    Designed to be used on ranges of elements.
    3f9cc0cd73
  50. Saibato commented at 12:20 pm on October 12, 2020: contributor

    Add #include <algorithm> to header.

    Tyi @hebasto while dev this i encountered and ugly wallet and filesystem edge case. that is only partly fixed by #18095 but with fewer changes and final here and in #19502 u might reach out to @luke-jr or @laanwj for more info.

  51. in src/wallet/walletutil.cpp:109 in 3f9cc0cd73
    122+                } else {
    123+                    // Found top-level btree file not called wallet.dat. Current bitcoin
    124+                    // software will never create these files but will allow them to be
    125+                    // opened in a shared database environment for backwards compatibility.
    126+                    // Add it to the list of available wallets.
    127+                    paths.emplace_back(it->path().filename());
    


    luke-jr commented at 7:27 pm on October 13, 2020:
    Why did you change this?

    Saibato commented at 7:48 pm on October 17, 2020:
    its not changed just the correct indent.

    Saibato commented at 10:30 pm on October 17, 2020:
    If u mean the whole logic itself, its because there where an other wallet access issue not mentioned here fixed also, could be no longer valid since we had some grave changes in master, i have to check, but since the PR its closed yet, it makes sense to let all as is and open two new and or wait until its reopened and then help out with the review.
  52. in src/wallet/walletutil.h:8 in 3f9cc0cd73
    4@@ -5,6 +5,7 @@
    5 #ifndef BITCOIN_WALLET_WALLETUTIL_H
    6 #define BITCOIN_WALLET_WALLETUTIL_H
    7 
    8+#include <algorithm>
    


    luke-jr commented at 7:32 pm on October 13, 2020:
    Why did you add this here? If it’s needed in the .cpp file, put it there…

    Saibato commented at 8:53 pm on October 17, 2020:
    ;was keen to see some compiler warnings, i though that was the hint from @hebasto to add <algorithm> addressed and changed back to .cpp that other bug we can fix later.
  53. luke-jr referenced this in commit 95c6413294 on Oct 13, 2020
  54. DrahtBot added the label Needs rebase on Oct 15, 2020
  55. DrahtBot commented at 11:09 am on October 15, 2020: member

    🐙 This pull request conflicts with the target branch and needs rebase.

    Want to unsubscribe from rebase notifications on this pull request? Just convert this pull request to a “draft”.

  56. laanwj added the label Up for grabs on Oct 16, 2020
  57. laanwj commented at 4:57 am on October 16, 2020: member
    Marking this as up for grabs. The concept to not iterate needlessly into directories that should not contain wallets definitely makes sense, but I think this makes unnecessary changes that are not well motivated.
  58. laanwj closed this on Oct 16, 2020

  59. Saibato commented at 8:58 pm on October 17, 2020: contributor

    Rebased and addressed https://github.com/bitcoin/bitcoin/commit/5a8f19eb331acbb1f7e2f52fe786ed21b30297b6 https://github.com/bitcoin/bitcoin/commit/4fb4fb716cd222ca8ae988d039328a66eb6e1f3b an comments, changed by this a lot so pls review again @luke-jr could not use ur code by merge and lost by fixup ur commit entrys, i hope u don;t mind.

    https://github.com/Saibato/bitcoin/tree/wallet_351

    Since this is closed here the rebase and changes are just in my tree, since github does not update closed pr tyi

  60. Saibato commented at 10:08 am on October 25, 2020: contributor

    to find wallets, that consumes time and could cause an unresponsive node. @laanwj “… cause an unresponsive node” in commit message was a hint, this PR is not about to fix something and must not be merged anyway but to point to some lines of code and its implications to gave others a chance to have a look in this and guess by themselfs. So my question is now, will have we have a fix and sure its not done if we just skip the boost traversing?

    in #19502 and #18095 we see some progress, but will that be enough and why have I to write this even, if it is to u so obvious?

  61. luke-jr commented at 2:23 pm on November 13, 2020: member

    @Saibato GitHub won’t let anyone reopen this since your branch changed. Can you git push ??? 3f9cc0cd736e79c563dee3573f0dab01dac10622:wallet_351 -f temporarily (you can re-push your new version after it’s reopened; put your repo name in place of ??? of course).

    Don’t forget to rebase!

    Also: You need to include <set> instead of <algorithm> ;)

  62. luke-jr referenced this in commit d4e0e38d11 on Nov 13, 2020
  63. luke-jr commented at 2:28 pm on November 13, 2020: member
  64. Saibato commented at 9:11 am on November 27, 2020: contributor
    @luke-jr tyi was the last week just counting my sats and had not looked in this, thx. for the reopen hint. btw look now why some wallets are missing when using the 0.21 rc1 tag, maybe that was the reason i changed also the scan for wallets logic here , but just forgot to mention that sggh…
  65. luke-jr referenced this in commit 17f214f4b7 on Oct 10, 2021
  66. MarcoFalke locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-18 15:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me