Skip to content

Commit e2f2df0

Browse files
committed
Merge bitcoin/bitcoin#32984: wallet: Set migrated wallet name only on success
060695c test: Failed load after migrate should restore backup (MarcoFalke) 8a4cfdd wallet: Set migrated wallet name only on success (Ava Chow) Pull request description: After a wallet is migrated and we are trying to load it, if it could not be loaded, don't try to set the wallet name. Otherwise we have a segfault. This can be tested by migrated a legacy wallet from another network (e.g. trying to migrate a testnet wallet on mainnet). The fixed behavior is return an error and restore the backup. ACKs for top commit: davidgumberg: ACK 060695c furszy: ACK 060695c rkrux: ACK 060695c w0xlt: reACK bitcoin/bitcoin@060695c pablomartin4btc: ACK 060695c Tree-SHA512: f4289e0b3dedef0a3d734c18604f2fd0df0dc65e9641bc342cfa45088d2540a3f6631bbea8bdd394b2631fa83b38e8ac37c83cfc4b53b19dcbd0b820a9beb6e4
2 parents 16f7b43 + 060695c commit e2f2df0

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

src/wallet/wallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4306,7 +4306,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
43064306
success = (wallet != nullptr);
43074307

43084308
// When no wallet is set, set the main wallet.
4309-
if (!res.wallet) {
4309+
if (success && !res.wallet) {
43104310
res.wallet_name = wallet->GetName();
43114311
res.wallet = std::move(wallet);
43124312
}

test/functional/wallet_migration.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ def assert_is_sqlite(self, wallet_name):
6565
assert_equal(file_magic, b'SQLite format 3\x00')
6666
assert_equal(self.master_node.get_wallet_rpc(wallet_name).getwalletinfo()["format"], "sqlite")
6767

68+
def assert_is_bdb(self, wallet_name):
69+
with open(self.master_node.wallets_path / wallet_name / self.wallet_data_filename, "rb") as f:
70+
data = f.read(16)
71+
_, _, magic = struct.unpack("QII", data)
72+
assert_equal(magic, BTREE_MAGIC)
73+
6874
def create_legacy_wallet(self, wallet_name, **kwargs):
6975
self.old_node.createwallet(wallet_name=wallet_name, descriptors=False, **kwargs)
7076
wallet = self.old_node.get_wallet_rpc(wallet_name)
@@ -916,10 +922,7 @@ def test_failed_migration_cleanup(self):
916922
assert_equal(original_shasum, new_shasum)
917923

918924
# Check the wallet we tried to migrate is still BDB
919-
with open(self.master_node.wallets_path / "failed" / "wallet.dat", "rb") as f:
920-
data = f.read(16)
921-
_, _, magic = struct.unpack("QII", data)
922-
assert_equal(magic, BTREE_MAGIC)
925+
self.assert_is_bdb("failed")
923926

924927
def test_blank(self):
925928
self.log.info("Test that a blank wallet is migrated")
@@ -1372,6 +1375,27 @@ def test_solvable_no_privs(self):
13721375
assert_equal(addr_info["solvable"], True)
13731376
assert "hex" in addr_info
13741377

1378+
def test_loading_failure_after_migration(self):
1379+
self.log.info("Test that a failed loading of the wallet at the end of migration restores the backup")
1380+
self.stop_node(self.old_node.index)
1381+
self.old_node.chain = "signet"
1382+
self.old_node.replace_in_config([("regtest=", "signet="), ("[regtest]", "[signet]")])
1383+
# Disable network sync and prevent disk space warning on small (tmp)fs
1384+
self.start_node(self.old_node.index, extra_args=self.old_node.extra_args + ["-maxconnections=0", "-prune=550"])
1385+
1386+
wallet_name = "failed_load_after_migrate"
1387+
self.create_legacy_wallet(wallet_name)
1388+
assert_raises_rpc_error(-4, "Wallet loading failed. Wallet files should not be reused across chains.", lambda: self.migrate_and_get_rpc(wallet_name))
1389+
1390+
# Check the wallet we tried to migrate is still BDB
1391+
self.assert_is_bdb(wallet_name)
1392+
1393+
self.stop_node(self.old_node.index)
1394+
self.old_node.chain = "regtest"
1395+
self.old_node.replace_in_config([("signet=", "regtest="), ("[signet]", "[regtest]")])
1396+
self.start_node(self.old_node.index)
1397+
self.connect_nodes(1, 0)
1398+
13751399
def run_test(self):
13761400
self.master_node = self.nodes[0]
13771401
self.old_node = self.nodes[1]
@@ -1404,6 +1428,7 @@ def run_test(self):
14041428
self.test_miniscript()
14051429
self.test_taproot()
14061430
self.test_solvable_no_privs()
1431+
self.test_loading_failure_after_migration()
14071432

14081433
if __name__ == '__main__':
14091434
WalletMigrationTest(__file__).main()

0 commit comments

Comments
 (0)