mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
wallet: add option to create in-memory SQLite DB in the migration
This commit is contained in:
parent
f409444d02
commit
ba8d151fe0
6 changed files with 20 additions and 13 deletions
|
@ -63,7 +63,7 @@ static void WalletMigration(benchmark::Bench& bench)
|
|||
|
||||
bench.epochs(/*numEpochs=*/1).epochIterations(/*numIters=*/1) // run the migration exactly once
|
||||
.run([&] {
|
||||
auto res{MigrateLegacyToDescriptor(std::move(wallet), /*passphrase=*/"", *loader->context(), /*was_loaded=*/false)};
|
||||
auto res{MigrateLegacyToDescriptor(std::move(wallet), /*passphrase=*/"", *loader->context(), /*was_loaded=*/false, /*in_memory=*/false)};
|
||||
assert(res);
|
||||
assert(res->wallet);
|
||||
assert(res->watchonly_wallet);
|
||||
|
|
|
@ -184,12 +184,13 @@ public:
|
|||
enum class DatabaseFormat {
|
||||
SQLITE,
|
||||
BERKELEY_RO,
|
||||
BERKELEY_SWAP,
|
||||
BERKELEY_SWAP
|
||||
};
|
||||
|
||||
struct DatabaseOptions {
|
||||
bool require_existing = false;
|
||||
bool require_create = false;
|
||||
bool in_memory = false;
|
||||
std::optional<DatabaseFormat> require_format;
|
||||
uint64_t create_flags = 0;
|
||||
SecureString create_passphrase;
|
||||
|
|
|
@ -695,7 +695,7 @@ std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const D
|
|||
{
|
||||
try {
|
||||
fs::path data_file = SQLiteDataFile(path);
|
||||
auto db = std::make_unique<SQLiteDatabase>(data_file.parent_path(), data_file, options);
|
||||
auto db = std::make_unique<SQLiteDatabase>(data_file.parent_path(), data_file, options, options.in_memory ? true : false);
|
||||
if (options.verify && !db->Verify(error)) {
|
||||
status = DatabaseStatus::FAILED_VERIFY;
|
||||
return nullptr;
|
||||
|
|
|
@ -4010,7 +4010,7 @@ util::Result<ScriptPubKeyMan*> CWallet::AddWalletDescriptor(WalletDescriptor& de
|
|||
return spk_man;
|
||||
}
|
||||
|
||||
bool CWallet::MigrateToSQLite(bilingual_str& error)
|
||||
bool CWallet::MigrateToSQLite(bilingual_str& error, bool in_memory)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
|
@ -4061,6 +4061,7 @@ bool CWallet::MigrateToSQLite(bilingual_str& error)
|
|||
DatabaseOptions opts;
|
||||
opts.require_create = true;
|
||||
opts.require_format = DatabaseFormat::SQLITE;
|
||||
opts.in_memory = in_memory;
|
||||
DatabaseStatus db_status;
|
||||
std::unique_ptr<WalletDatabase> new_db = MakeDatabase(wallet_path, opts, db_status, error);
|
||||
assert(new_db); // This is to prevent doing anything further with this wallet. The original file was deleted, but a backup exists.
|
||||
|
@ -4476,10 +4477,10 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
|||
return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
|
||||
}
|
||||
|
||||
return MigrateLegacyToDescriptor(std::move(local_wallet), passphrase, context, was_loaded);
|
||||
return MigrateLegacyToDescriptor(std::move(local_wallet), passphrase, context, was_loaded, /*in_memory=*/false);
|
||||
}
|
||||
|
||||
util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool was_loaded)
|
||||
util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool was_loaded, bool in_memory)
|
||||
{
|
||||
MigrationResult res;
|
||||
bilingual_str error;
|
||||
|
@ -4541,7 +4542,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
|
|||
{
|
||||
LOCK(local_wallet->cs_wallet);
|
||||
// First change to using SQLite
|
||||
if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
|
||||
if (!local_wallet->MigrateToSQLite(error, in_memory)) return util::Error{error};
|
||||
|
||||
// Do the migration of keys and scripts for non-empty wallets, and cleanup if it fails
|
||||
if (HasLegacyRecords(*local_wallet)) {
|
||||
|
@ -4580,7 +4581,10 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
|
|||
// Migration failed, cleanup
|
||||
// Before deleting the wallet's directory, copy the backup file to the top-level wallets dir
|
||||
fs::path temp_backup_location = fsbridge::AbsPathJoin(GetWalletDir(), backup_filename);
|
||||
fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
|
||||
|
||||
if (!in_memory) {
|
||||
fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
|
||||
}
|
||||
|
||||
// Make list of wallets to cleanup
|
||||
std::vector<std::shared_ptr<CWallet>> created_wallets;
|
||||
|
@ -4625,8 +4629,10 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
|
|||
}
|
||||
|
||||
// The wallet directory has been restored, but just in case, copy the previously created backup to the wallet dir
|
||||
fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
|
||||
fs::remove(temp_backup_location);
|
||||
if (!in_memory) {
|
||||
fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
|
||||
fs::remove(temp_backup_location);
|
||||
}
|
||||
|
||||
// Verify that there is no dangling wallet: when the wallet wasn't loaded before, expect null.
|
||||
// This check is performed after restoration to avoid an early error before saving the backup.
|
||||
|
|
|
@ -1046,7 +1046,7 @@ public:
|
|||
* A backup is not created.
|
||||
* May crash if something unexpected happens in the filesystem.
|
||||
*/
|
||||
bool MigrateToSQLite(bilingual_str& error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool MigrateToSQLite(bilingual_str& error, bool in_memory = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
//! Get all of the descriptors from a legacy wallet
|
||||
std::optional<MigrationData> GetDescriptorsForLegacy(bilingual_str& error) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
@ -1137,7 +1137,7 @@ struct MigrationResult {
|
|||
//! Do all steps to migrate a legacy wallet to a descriptor wallet
|
||||
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context);
|
||||
//! Requirement: The wallet provided to this function must be isolated, with no attachment to the node's context.
|
||||
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool was_loaded);
|
||||
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool was_loaded, bool in_memory);
|
||||
} // namespace wallet
|
||||
|
||||
#endif // BITCOIN_WALLET_WALLET_H
|
||||
|
|
|
@ -1427,7 +1427,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
|||
{
|
||||
bool exists;
|
||||
try {
|
||||
exists = fs::symlink_status(path).type() != fs::file_type::not_found;
|
||||
exists = fs::symlink_status(path).type() != fs::file_type::not_found && !options.in_memory;
|
||||
} catch (const fs::filesystem_error& e) {
|
||||
error = Untranslated(strprintf("Failed to access database path '%s': %s", fs::PathToString(path), fsbridge::get_filesystem_error_message(e)));
|
||||
status = DatabaseStatus::FAILED_BAD_PATH;
|
||||
|
|
Loading…
Add table
Reference in a new issue