Repository: bitcoin/bitcoin
File: test/functional/wallet_migration.py (Python)

Code before:

        # TODO: Test the actual records in the wallet for these tests too. The behavior may be correct, but the data written may not be what we actually want
        self.test_basic()
        self.test_multisig()
        self.test_other_watchonly()
        self.test_no_privkeys()
        self.test_pk_coinbases()
        self.test_encrypted()
        self.test_nonexistent()
        self.test_unloaded_by_path()
        self.test_default_wallet_failure()
        self.test_default_wallet()
        self.test_default_wallet_watch_only()
        self.test_direct_file()
        self.test_addressbook()
        self.test_migrate_raw_p2sh()
        self.test_conflict_txs()
        self.test_hybrid_pubkey()
        self.test_failed_migration_cleanup()
        self.test_avoidreuse()
        self.test_preserve_tx_extra_info()
        self.test_blank()
        self.test_migrate_simple_watch_only()
        self.test_manual_keys_import()
        self.test_p2wsh()
        self.test_disallowed_p2wsh()
        self.test_miniscript()
        self.test_taproot()
        self.test_solvable_no_privs()

        # Note: After this test the first 250 blocks of 'master_node' are pruned
        self.unsynced_wallet_on_pruned_node_fails()

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


Review comment (bug):
How is this test passing?

We first attempt to migrate the wallet and fail, then call `loadwallet` with the same bdb wallet when v29 has them disabled by default. 
The `master_node` is not restarted with `-deprecatedrpc=create_bdb` so `master_node.loadwallet` should be throwing a "Build does not support Berkeley DB database format".

Code after:
        shutil.copyfile(self.old_node.wallets_path / "wallet.dat", self.master_node.wallets_path / "wallet.dat")

        # Generate blocks just so the wallet best block is pruned
        self.restart_node(0, ["-fastprune", "-prune=1", "-nowallet"])
        self.connect_nodes(0, 1)
        self.generate(self.master_node, 450, sync_fun=self.no_op)
        self.master_node.pruneblockchain(250)
        # Ensure next block to sync is unavailable
        assert_raises_rpc_error(-1, "Block not available (pruned data)", self.master_node.getblock, self.master_node.getblockhash(last_wallet_synced_block + 1))

        # Check migration failure
        mocked_time = int(time.time())
        self.master_node.setmocktime(mocked_time)
        assert_raises_rpc_error(-4, "last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)", self.master_node.migratewallet, wallet_name="")
        self.master_node.setmocktime(0)

        # Verify the /wallets/ path exists, the wallet is still BDB and the backup file is there.
        assert self.master_node.wallets_path.exists()

        with open(self.master_node.wallets_path / "wallet.dat", "rb") as f:
            data = f.read(16)
            _, _, magic = struct.unpack("QII", data)
            assert_equal(magic, BTREE_MAGIC)

        backup_path = self.master_node.wallets_path / f"default_wallet_{mocked_time}.legacy.bak"
        assert backup_path.exists()

        self.clear_default_wallet(backup_path)


    def run_test(self):
        self.master_node = self.nodes[0]
        self.old_node = self.nodes[1]

        self.generate(self.master_node, 101)

        # TODO: Test the actual records in the wallet for these tests too. The behavior may be correct, but the data written may not be what we actually want
        self.test_basic()
        self.test_multisig()
        self.test_other_watchonly()
        self.test_no_privkeys()
        self.test_pk_coinbases()
        self.test_encrypted()
        self.test_nonexistent()
        self.test_unloaded_by_path()

        migration_failure_cases = [
            "",
            "../",
            os.path.abspath(self.master_node.datadir_path / "absolute_path"),
            "normallynamedwallet"