Skip to content

Commit b21ba08

Browse files
committed
Merge bitcoin/bitcoin#30265: wallet: Fix listwalletdir listing of migrated default 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
2 parents 012baa4 + 6b2dcba commit b21ba08

File tree

2 files changed

+8
-3
lines changed

2 files changed

+8
-3
lines changed

src/wallet/db.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
4242
(IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
4343
// Found a directory which contains wallet.dat btree file, add it as a wallet.
4444
paths.emplace_back(path);
45-
} else if (it.depth() == 0 && it->symlink_status().type() == fs::file_type::regular && IsBDBFile(it->path())) {
45+
} else if (it.depth() == 0 && it->symlink_status().type() == fs::file_type::regular && it->path().extension() != ".bak") {
4646
if (it->path().filename() == "wallet.dat") {
4747
// Found top-level wallet.dat btree file, add top level directory ""
4848
// as a wallet.
4949
paths.emplace_back();
50-
} else {
50+
} else if (IsBDBFile(it->path())) {
5151
// Found top-level btree file not called wallet.dat. Current bitcoin
5252
// software will never create these files but will allow them to be
5353
// opened in a shared database environment for backwards compatibility.

test/functional/wallet_migration.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,10 +548,15 @@ def test_default_wallet(self):
548548
assert_equal(info["descriptors"], True)
549549
assert_equal(info["format"], "sqlite")
550550

551+
walletdir_list = wallet.listwalletdir()
552+
assert {"name": info["walletname"]} in walletdir_list["wallets"]
553+
551554
# Check backup existence and its non-empty wallet filename
552-
backup_path = self.nodes[0].wallets_path / f'default_wallet_{curr_time}.legacy.bak'
555+
backup_filename = f"default_wallet_{curr_time}.legacy.bak"
556+
backup_path = self.nodes[0].wallets_path / backup_filename
553557
assert backup_path.exists()
554558
assert_equal(str(backup_path), res['backup_path'])
559+
assert {"name": backup_filename} not in walletdir_list["wallets"]
555560

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

0 commit comments

Comments
 (0)