Skip to content

Commit 0c24748

Browse files
ryanofskyvijaydasmp
authored andcommitted
Merge bitcoin#28976: wallet: Fix migration of blank wallets
c11c404 tests: Test migration of blank wallets (Andrew Chow) 563b2a6 wallet: Better error message when missing LegacySPKM during migration (Andrew Chow) b1d2c77 wallet: Check for descriptors flag before migration (Andrew Chow) 8c127ff wallet: Skip key and script migration for blank wallets (Andrew Chow) Pull request description: Blank wallets (wallets without any keys are scripts) are being detected as already being descriptor wallets even though they are not. This is because the check for whether a wallet is already a descriptor wallet uses the presence of a `LegacyScriptPubKeyMan` which is only setup when keys or scripts are found. This PR resolves this issue by checking for the descriptor wallet flag instead and subsequently skipping the keys and scripts part of migration for blank wallets. Fixes the issue mentioned in bitcoin#28868 (comment) ACKs for top commit: furszy: reACK c11c404. CI failure is unrelated. ryanofsky: Code review ACK c11c404 Tree-SHA512: 2466fdf1542eb8489c841253191f85dc88365493f0bb3395b67dee3e43709a9993c68b9d7623657b54b779adbe68fc81962d60efef4802c5d461f154167af7f4
1 parent dac3c8d commit 0c24748

2 files changed

Lines changed: 25 additions & 9 deletions

File tree

src/wallet/wallet.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4401,7 +4401,11 @@ std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& err
44014401
AssertLockHeld(cs_wallet);
44024402

44034403
LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan();
4404-
assert(legacy_spkm);
4404+
if (!Assume(legacy_spkm)) {
4405+
// This shouldn't happen
4406+
error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));
4407+
return std::nullopt;
4408+
}
44054409

44064410
std::optional<MigrationData> res = legacy_spkm->MigrateToDescriptor();
44074411
if (res == std::nullopt) {
@@ -4416,8 +4420,9 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
44164420
AssertLockHeld(cs_wallet);
44174421

44184422
LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan();
4419-
if (!legacy_spkm) {
4420-
error = _("Error: This wallet is already a descriptor wallet");
4423+
if (!Assume(legacy_spkm)) {
4424+
// This shouldn't happen
4425+
error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));
44214426
return false;
44224427
}
44234428

@@ -4743,7 +4748,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
47434748
}
47444749

47454750
// Before anything else, check if there is something to migrate.
4746-
if (!local_wallet->GetLegacyScriptPubKeyMan()) {
4751+
if (local_wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
47474752
return util::Error{_("Error: This wallet is already a descriptor wallet")};
47484753
}
47494754

@@ -4790,8 +4795,11 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
47904795
// First change to using SQLite
47914796
if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
47924797

4793-
// Do the migration, and cleanup if it fails
4794-
success = DoMigration(*local_wallet, context, error, res);
4798+
// Do the migration of keys and scripts for non-blank wallets, and cleanup if it fails
4799+
success = local_wallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
4800+
if (!success) {
4801+
success = DoMigration(*local_wallet, context, error, res);
4802+
}
47954803
}
47964804

47974805
if (success) {

test/functional/wallet_migration.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,12 @@ def assert_is_sqlite(self, wallet_name):
3737
assert_equal(file_magic, b'SQLite format 3\x00')
3838
assert_equal(self.nodes[0].get_wallet_rpc(wallet_name).getwalletinfo()["format"], "sqlite")
3939

40-
def create_legacy_wallet(self, wallet_name, disable_private_keys=False):
41-
self.nodes[0].createwallet(wallet_name=wallet_name, descriptors=False, disable_private_keys=disable_private_keys)
40+
def create_legacy_wallet(self, wallet_name, **kwargs):
41+
self.nodes[0].createwallet(wallet_name=wallet_name, descriptors=False, **kwargs)
4242
wallet = self.nodes[0].get_wallet_rpc(wallet_name)
4343
info = wallet.getwalletinfo()
4444
assert_equal(info["descriptors"], False)
4545
assert_equal(info["format"], "bdb")
46-
assert_equal(info["private_keys_enabled"], not disable_private_keys)
4746
return wallet
4847

4948
def assert_addr_info_equal(self, addr_info, addr_info_old):
@@ -532,6 +531,14 @@ def test_wallet_name_with_slashes(self):
532531

533532
self.assert_is_sqlite(nested_name)
534533

534+
def test_blank(self):
535+
self.log.info("Test that a blank wallet is migrated")
536+
wallet = self.create_legacy_wallet("blank", blank=True)
537+
assert_equal(wallet.getwalletinfo()["blank"], True)
538+
wallet.migratewallet()
539+
assert_equal(wallet.getwalletinfo()["blank"], True)
540+
541+
535542
def run_test(self):
536543
self.generate(self.nodes[0], 101)
537544

@@ -545,6 +552,7 @@ def run_test(self):
545552
self.test_unloaded()
546553
self.test_unloaded_by_path()
547554
self.test_wallet_name_with_slashes()
555+
self.test_blank()
548556

549557
if __name__ == '__main__':
550558
WalletMigrationTest().main()

0 commit comments

Comments
 (0)