Skip to content

Commit

Permalink
Merge bitcoin#30265: wallet: Fix listwalletdir listing of migrated de…
Browse files Browse the repository at this point in the history
…fault wallets and generated backup files

6b2dcba wallet: List sqlite wallets with empty string name (Ava Chow)
3ddbdd1 wallet: Ignore .bak files when listing wallet files (Ava Chow)

Pull request description:

  When the default wallet is migrated, we do not rename the wallet so we end up having a descriptor wallet with the empty string as its name and the wallet.dat file in the root of the walletdir. This is supposed to be an unsupported configuration and there is no other way to achieve this (other than file copying), but the wallet loading code does not disallow loading such wallets. However `listwalletdir` does not currently list the default wallet if it is sqlite. This is confusing to users, so change `listwalletdir` to include these wallets.

  Additionally, the migration of the default wallet, and of any plain wallet files in the walletdir, produces a backup file in the walletdir itself. Since these backups are a BDB file, `listwalletdir` will detect them as being another wallet that we could open, but this is erroneous and could lead to confusion and potentially funds loss if both the backup and the migrated wallet are in use simultaneously. To reduce the likelihood of this issue, don't list these wallets in `listwalletdir`.

  ***

  Possibly we could have more stringent checks on loading to resolve these issues, but I'm concerned that that will just confuse users and gratuitously break things that already worked.

  Since the original intent was to disallow default wallets for sqlite/descriptors, a possible alternative would be to prevent people from loading such wallets and change migration to rename those wallets. However, given that this behavior with migrating default wallets has existed since default wallet migration was fixed, I think that making such a change would be confusing and break things for no good reason. Although perhaps we should still do the renaming.

  For the backups, we could also change loading to refuse to load any wallet named with `.bak` (or `.legacy.bak`) as such wallets can still be loaded by giving the path to them directly, which some users may do to "restore" the backup. However restricting what can be loaded based on filename seems a little heavyhanded. It wouldn't be funds loss though since the correct way to restore the backup is with `restorewallet`.

ACKs for top commit:
  fjahr:
    Code review ACK 6b2dcba
  furszy:
    Code ACK  6b2dcba
  glozow:
    ACK 6b2dcba

Tree-SHA512: 0b033f6ed55830f8a054afea3fb2cf1fa82a94040053ebfaf123bda36c99f45d3f01a2aec4ed02fed9c61bb3d320b047ed892d7f6644b5a356a7bc5974b10cff
  • Loading branch information
glozow committed Aug 12, 2024
2 parents 012baa4 + 6b2dcba commit b21ba08
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 3 deletions.
4 changes: 2 additions & 2 deletions src/wallet/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
(IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
// Found a directory which contains wallet.dat btree file, add it as a wallet.
paths.emplace_back(path);
} else if (it.depth() == 0 && it->symlink_status().type() == fs::file_type::regular && IsBDBFile(it->path())) {
} else if (it.depth() == 0 && it->symlink_status().type() == fs::file_type::regular && it->path().extension() != ".bak") {
if (it->path().filename() == "wallet.dat") {
// Found top-level wallet.dat btree file, add top level directory ""
// as a wallet.
paths.emplace_back();
} else {
} else if (IsBDBFile(it->path())) {
// Found top-level btree file not called wallet.dat. Current bitcoin
// software will never create these files but will allow them to be
// opened in a shared database environment for backwards compatibility.
Expand Down
7 changes: 6 additions & 1 deletion test/functional/wallet_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,10 +548,15 @@ def test_default_wallet(self):
assert_equal(info["descriptors"], True)
assert_equal(info["format"], "sqlite")

walletdir_list = wallet.listwalletdir()
assert {"name": info["walletname"]} in walletdir_list["wallets"]

# Check backup existence and its non-empty wallet filename
backup_path = self.nodes[0].wallets_path / f'default_wallet_{curr_time}.legacy.bak'
backup_filename = f"default_wallet_{curr_time}.legacy.bak"
backup_path = self.nodes[0].wallets_path / backup_filename
assert backup_path.exists()
assert_equal(str(backup_path), res['backup_path'])
assert {"name": backup_filename} not in walletdir_list["wallets"]

def test_direct_file(self):
self.log.info("Test migration of a wallet that is not in a wallet directory")
Expand Down

0 comments on commit b21ba08

Please sign in to comment.