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

Code before:
        open(invalid_wallet_file, 'a', encoding="utf8").write('invald wallet')
        wallet_name = "res0"
        not_created_wallet_file = node.wallets_path / wallet_name
        error_message = "Wallet file verification failed. Failed to load database path '{}'. Data is not in recognized format.".format(not_created_wallet_file)
        assert_raises_rpc_error(-18, error_message, node.restorewallet, wallet_name, invalid_wallet_file)
        assert not not_created_wallet_file.exists()

    def restore_nonexistent_wallet(self):
        node = self.nodes[3]
        nonexistent_wallet_file = self.nodes[0].datadir_path / 'nonexistent_wallet.bak'
        wallet_name = "res0"
        assert_raises_rpc_error(-8, "Backup file does not exist", node.restorewallet, wallet_name, nonexistent_wallet_file)
        not_created_wallet_file = node.wallets_path / wallet_name
        assert not not_created_wallet_file.exists()

    def restore_wallet_existent_name(self):
        node = self.nodes[3]
        backup_file = self.nodes[0].datadir_path / 'wallet.bak'
        wallet_name = "res0"
        wallet_file = node.wallets_path / wallet_name
        error_message = "Failed to create database path '{}'. Database already exists.".format(wallet_file)
        assert_raises_rpc_error(-36, error_message, node.restorewallet, wallet_name, backup_file)
        assert wallet_file.exists()

    def run_test(self):
        self.log.info("Generating initial blockchain")
        self.generate(self.nodes[0], 1)
        self.generate(self.nodes[1], 1)
        self.generate(self.nodes[2], 1)
        self.generate(self.nodes[3], COINBASE_MATURITY)

        assert_equal(self.nodes[0].getbalance(), 50)
        assert_equal(self.nodes[1].getbalance(), 50)
        assert_equal(self.nodes[2].getbalance(), 50)
        assert_equal(self.nodes[3].getbalance(), 0)

        self.log.info("Creating transactions")
        # Five rounds of sending each other transactions.
        for _ in range(5):
            self.do_one_round()

        self.log.info("Backing up")

        for node_num in range(3):
            self.nodes[node_num].backupwallet(self.nodes[node_num].datadir_path / 'wallet.bak')

        if not self.options.descriptors:
            for node_num in range(3):
                self.nodes[node_num].dumpwallet(self.nodes[node_num].datadir_path / 'wallet.dump')

        self.log.info("More transactions")

Review comment (suggestion):
nit
```suggestion
        self.log.info("Test loading backup on a pruned node when the backup was created close to the prune height of the restoring node")

```

Code after:
        open(invalid_wallet_file, 'a', encoding="utf8").write('invald wallet')
        wallet_name = "res0"
        not_created_wallet_file = node.wallets_path / wallet_name
        error_message = "Wallet file verification failed. Failed to load database path '{}'. Data is not in recognized format.".format(not_created_wallet_file)
        assert_raises_rpc_error(-18, error_message, node.restorewallet, wallet_name, invalid_wallet_file)
        assert not not_created_wallet_file.exists()

    def restore_nonexistent_wallet(self):
        node = self.nodes[3]
        nonexistent_wallet_file = self.nodes[0].datadir_path / 'nonexistent_wallet.bak'
        wallet_name = "res0"
        assert_raises_rpc_error(-8, "Backup file does not exist", node.restorewallet, wallet_name, nonexistent_wallet_file)
        not_created_wallet_file = node.wallets_path / wallet_name
        assert not not_created_wallet_file.exists()

    def restore_wallet_existent_name(self):
        node = self.nodes[3]
        backup_file = self.nodes[0].datadir_path / 'wallet.bak'
        wallet_name = "res0"
        wallet_file = node.wallets_path / wallet_name
        error_message = "Failed to create database path '{}'. Database already exists.".format(wallet_file)
        assert_raises_rpc_error(-36, error_message, node.restorewallet, wallet_name, backup_file)
        assert wallet_file.exists()

    def test_pruned_wallet_backup(self):
        self.log.info("Test loading backup on a pruned node when the backup was created close to the prune height of the restoring node")
        node = self.nodes[3]
        self.restart_node(3, ["-prune=1", "-fastprune=1"])
        # Ensure the chain tip is at height 214, because this test assume it is.
        assert_equal(node.getchaintips()[0]["height"], 214)
        # We need a few more blocks so we can actually get above an realistic
        # minimal prune height
        self.generate(node, 50, sync_fun=self.no_op)
        # Backup created at block height 264
        node.backupwallet(node.datadir_path / 'wallet_pruned.bak')
        # Generate more blocks so we can actually prune the older blocks
        self.generate(node, 300, sync_fun=self.no_op)
        # This gives us an actual prune height roughly in the range of 220 - 240
        node.pruneblockchain(250)
        # The backup should be updated with the latest height (locator) for
        # the backup to load successfully this close to the prune height
        node.restorewallet(f'pruned', node.datadir_path / 'wallet_pruned.bak')

    def run_test(self):
        self.log.info("Generating initial blockchain")
        self.generate(self.nodes[0], 1)
        self.generate(self.nodes[1], 1)
        self.generate(self.nodes[2], 1)
        self.generate(self.nodes[3], COINBASE_MATURITY)

        assert_equal(self.nodes[0].getbalance(), 50)