Skip to content

Commit 517e204

Browse files
committed
Change MigrateLegacyToDescriptor to reopen wallet as BERKELEY_RO
When we reopen the wallet to do the migration, instead of opening using BDB, open it using the BerkeleyRO implementation.
1 parent a786fd2 commit 517e204

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/wallet/wallet.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2923,7 +2923,7 @@ bool CWallet::EraseAddressReceiveRequest(WalletBatch& batch, const CTxDestinatio
29232923
return true;
29242924
}
29252925

2926-
std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error_string)
2926+
static util::Result<fs::path> GetWalletPath(const std::string& name)
29272927
{
29282928
// Do some checking on wallet path. It should be either a:
29292929
//
@@ -2936,15 +2936,24 @@ std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, cons
29362936
if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
29372937
(path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
29382938
(path_type == fs::file_type::regular && fs::PathFromString(name).filename() == fs::PathFromString(name)))) {
2939-
error_string = Untranslated(strprintf(
2939+
return util::Error{Untranslated(strprintf(
29402940
"Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
29412941
"database/log.?????????? files can be stored, a location where such a directory could be created, "
29422942
"or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2943-
name, fs::quoted(fs::PathToString(GetWalletDir()))));
2943+
name, fs::quoted(fs::PathToString(GetWalletDir()))))};
2944+
}
2945+
return wallet_path;
2946+
}
2947+
2948+
std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error_string)
2949+
{
2950+
const auto& wallet_path = GetWalletPath(name);
2951+
if (!wallet_path) {
2952+
error_string = util::ErrorString(wallet_path);
29442953
status = DatabaseStatus::FAILED_BAD_PATH;
29452954
return nullptr;
29462955
}
2947-
return MakeDatabase(wallet_path, options, status, error_string);
2956+
return MakeDatabase(*wallet_path, options, status, error_string);
29482957
}
29492958

29502959
std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
@@ -4346,11 +4355,24 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
43464355
// If the wallet is still loaded, unload it so that nothing else tries to use it while we're changing it
43474356
bool was_loaded = false;
43484357
if (auto wallet = GetWallet(context, wallet_name)) {
4358+
if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4359+
return util::Error{_("Error: This wallet is already a descriptor wallet")};
4360+
}
4361+
43494362
if (!RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt, warnings)) {
43504363
return util::Error{_("Unable to unload the wallet before migrating")};
43514364
}
43524365
UnloadWallet(std::move(wallet));
43534366
was_loaded = true;
4367+
} else {
4368+
// Check if the wallet is BDB
4369+
const auto& wallet_path = GetWalletPath(wallet_name);
4370+
if (!wallet_path) {
4371+
return util::Error{util::ErrorString(wallet_path)};
4372+
}
4373+
if (!IsBDBFile(BDBDataFile(*wallet_path))) {
4374+
return util::Error{_("Error: This wallet is already a descriptor wallet")};
4375+
}
43544376
}
43554377

43564378
// Load the wallet but only in the context of this function.
@@ -4359,6 +4381,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
43594381
empty_context.args = context.args;
43604382
DatabaseOptions options;
43614383
options.require_existing = true;
4384+
options.require_format = DatabaseFormat::BERKELEY_RO;
43624385
DatabaseStatus status;
43634386
std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
43644387
if (!database) {
@@ -4373,6 +4396,8 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
43734396

43744397
// Helper to reload as normal for some of our exit scenarios
43754398
const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4399+
// Reset options.require_format as wallets of any format may be reloaded.
4400+
options.require_format = std::nullopt;
43764401
assert(to_reload.use_count() == 1);
43774402
std::string name = to_reload->GetName();
43784403
to_reload.reset();

test/functional/wallet_migration.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,13 @@ def test_basic(self):
205205
self.assert_list_txs_equal(basic2.listtransactions(), basic2_txs)
206206

207207
# Now test migration on a descriptor wallet
208-
self.log.info("Test \"nothing to migrate\" when the user tries to migrate a wallet with no legacy data")
208+
self.log.info("Test \"nothing to migrate\" when the user tries to migrate a loaded wallet with no legacy data")
209209
assert_raises_rpc_error(-4, "Error: This wallet is already a descriptor wallet", basic2.migratewallet)
210210

211+
self.log.info("Test \"nothing to migrate\" when the user tries to migrate an unloaded wallet with no legacy data")
212+
basic2.unloadwallet()
213+
assert_raises_rpc_error(-4, "Error: This wallet is already a descriptor wallet", self.nodes[0].migratewallet, "basic2")
214+
211215
def test_multisig(self):
212216
default = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
213217

0 commit comments

Comments
 (0)