diff --git a/src/wallet/export.cpp b/src/wallet/export.cpp index 6f170dd728e..1df51b6b260 100644 --- a/src/wallet/export.cpp +++ b/src/wallet/export.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -69,40 +70,15 @@ util::Result ExportWatchOnlyWallet(const CWallet& wallet, const fs: return util::Error{_("Error: Wallet has no descriptors to export")}; } - // Setup DatabaseOptions to create a new sqlite database - DatabaseOptions options; - options.require_existing = false; - options.require_create = true; - options.require_format = DatabaseFormat::SQLITE; - // Make the wallet with the same flags as this wallet, but without private keys - options.create_flags = wallet.GetWalletFlags() | WALLET_FLAG_DISABLE_PRIVATE_KEYS; + const uint64_t create_flags = wallet.GetWalletFlags() | WALLET_FLAG_DISABLE_PRIVATE_KEYS; - // Make the watchonly wallet - DatabaseStatus status; + // Create the temporary watchonly wallet in memory to avoid leaving files on disk std::vector warnings; - std::string wallet_name = wallet.GetName() + "_watchonly_temp"; bilingual_str error; - std::unique_ptr database = MakeWalletDatabase(wallet_name, options, status, error); - if (!database) { - return util::Error{strprintf(_("Wallet file creation failed: %s"), error)}; - } - - // Always remove the temporary wallet files, even when returning early on error. - std::shared_ptr watchonly_wallet; - fs::path wallet_path = fs::PathFromString(database->Filename()).parent_path(); - std::vector cleanup_files = database->Files(); - auto cleanup_watchonly_wallet = interfaces::MakeCleanupHandler([&watchonly_wallet, &wallet_path, &cleanup_files] { - if (watchonly_wallet) watchonly_wallet.reset(); - for (const auto& file : cleanup_files) { - fs::remove(file); - } - fs::remove(wallet_path); - }); - WalletContext empty_context; empty_context.args = context.args; - watchonly_wallet = CWallet::CreateNew(empty_context, wallet_name, std::move(database), options.create_flags, /*born_encrypted=*/false, error, warnings); + std::shared_ptr watchonly_wallet = CWallet::CreateNew(empty_context, /*name=*/wallet.GetName() + "_watchonly_temp", MakeInMemoryWalletDatabase(), create_flags, /*born_encrypted=*/false, error, warnings); if (!watchonly_wallet) { return util::Error{strprintf(_("Error: Failed to create new watchonly wallet. %s"), error)}; } diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp index 28123ecf4f4..fa2abc93a51 100644 --- a/src/wallet/sqlite.cpp +++ b/src/wallet/sqlite.cpp @@ -722,6 +722,15 @@ std::unique_ptr MakeSQLiteDatabase(const fs::path& path, const D } } +InMemoryWalletDatabase::InMemoryWalletDatabase() + : SQLiteDatabase(fs::path{}, fs::path{":memory:"}, DatabaseOptions(), SQLITE_OPEN_MEMORY) +{} + +std::unique_ptr MakeInMemoryWalletDatabase() +{ + return std::make_unique(); +} + std::string SQLiteDatabaseVersion() { return std::string(sqlite3_libversion()); diff --git a/src/wallet/sqlite.h b/src/wallet/sqlite.h index 3a35bb24bba..f3268b4b490 100644 --- a/src/wallet/sqlite.h +++ b/src/wallet/sqlite.h @@ -175,8 +175,19 @@ public: bool m_use_unsafe_sync; }; +/** An in-memory SQLiteDatabase. Used as a temporary build artifact where no + * on-disk persistence is needed. */ +class InMemoryWalletDatabase : public SQLiteDatabase +{ +public: + InMemoryWalletDatabase(); + std::vector Files() override { return {}; } +}; + std::unique_ptr MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error); +std::unique_ptr MakeInMemoryWalletDatabase(); + std::string SQLiteDatabaseVersion(); } // namespace wallet diff --git a/src/wallet/test/util.cpp b/src/wallet/test/util.cpp index 43cfd40fabd..19281be63bd 100644 --- a/src/wallet/test/util.cpp +++ b/src/wallet/test/util.cpp @@ -116,7 +116,7 @@ CTxDestination getNewDestination(CWallet& w, OutputType output_type) } MockableSQLiteDatabase::MockableSQLiteDatabase() - : SQLiteDatabase(fs::PathFromString("mock/"), fs::PathFromString("mock/wallet.dat"), DatabaseOptions(), SQLITE_OPEN_MEMORY) + : InMemoryWalletDatabase() {} std::unique_ptr CreateMockableWalletDatabase() diff --git a/src/wallet/test/util.h b/src/wallet/test/util.h index 9a407d31025..0af46e5577a 100644 --- a/src/wallet/test/util.h +++ b/src/wallet/test/util.h @@ -56,7 +56,7 @@ public: /** A WalletDatabase whose contents and return values can be modified as needed for testing **/ -class MockableSQLiteDatabase : public SQLiteDatabase +class MockableSQLiteDatabase : public InMemoryWalletDatabase { public: MockableSQLiteDatabase(); @@ -64,7 +64,6 @@ public: bool Backup(const std::string& strDest) const override { return true; } std::string Filename() override { return "mockable"; } - std::vector Files() override { return {}; } std::string Format() override { return "sqlite-mock"; } std::unique_ptr MakeBatch() override { return std::make_unique(*this); } };