aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chow <achow101-github@achow101.com>2020-05-08 17:06:16 -0400
committerAndrew Chow <achow101-github@achow101.com>2020-05-25 12:36:48 -0400
commitc87770915b88d195d264b58111c64142b1965cfa (patch)
treea150e2e78a68ff57912d7baa57d65eea6f947749
parent448bdff26307981b7e32ba5610dad6674c1fe46d (diff)
downloadbitcoin-c87770915b88d195d264b58111c64142b1965cfa.tar.xz
wallettool: Add a salvage command
-rw-r--r--src/bitcoin-wallet.cpp1
-rw-r--r--src/wallet/wallettool.cpp38
2 files changed, 34 insertions, 5 deletions
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index 7f9439788a..b420463c00 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -31,6 +31,7 @@ static void SetupWalletToolArgs()
gArgs.AddArg("info", "Get wallet info", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
gArgs.AddArg("create", "Create new wallet file", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
+ gArgs.AddArg("salvage", "Attempt to recover private keys from a corrupt wallet", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
}
static bool WalletAppInit(int argc, char* argv[])
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
index 522efaa884..89645fb5cd 100644
--- a/src/wallet/wallettool.cpp
+++ b/src/wallet/wallettool.cpp
@@ -103,6 +103,29 @@ static void WalletShowInfo(CWallet* wallet_instance)
tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
}
+static bool SalvageWallet(const fs::path& path)
+{
+ // Create a Database handle to allow for the db to be initialized before recovery
+ std::unique_ptr<WalletDatabase> database = WalletDatabase::Create(path);
+
+ // Initialize the environment before recovery
+ bilingual_str error_string;
+ try {
+ WalletBatch::VerifyEnvironment(path, error_string);
+ } catch (const fs::filesystem_error& e) {
+ error_string = Untranslated(strprintf("Error loading wallet. %s", fsbridge::get_filesystem_error_message(e)));
+ }
+ if (!error_string.original.empty()) {
+ tfm::format(std::cerr, "Failed to open wallet for salvage :%s\n", error_string.original);
+ return false;
+ }
+
+ // Perform the recovery
+ CWallet dummy_wallet(nullptr, WalletLocation(), WalletDatabase::CreateDummy());
+ std::string backup_filename;
+ return WalletBatch::Recover(path, (void*)&dummy_wallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename);
+}
+
bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
{
fs::path path = fs::absolute(name, GetWalletDir());
@@ -113,7 +136,7 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
WalletShowInfo(wallet_instance.get());
wallet_instance->Flush(true);
}
- } else if (command == "info") {
+ } else if (command == "info" || command == "salvage") {
if (!fs::exists(path)) {
tfm::format(std::cerr, "Error: no wallet file at %s\n", name);
return false;
@@ -123,10 +146,15 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
tfm::format(std::cerr, "%s\nError loading %s. Is wallet being used by other process?\n", error.original, name);
return false;
}
- std::shared_ptr<CWallet> wallet_instance = LoadWallet(name, path);
- if (!wallet_instance) return false;
- WalletShowInfo(wallet_instance.get());
- wallet_instance->Flush(true);
+
+ if (command == "info") {
+ std::shared_ptr<CWallet> wallet_instance = LoadWallet(name, path);
+ if (!wallet_instance) return false;
+ WalletShowInfo(wallet_instance.get());
+ wallet_instance->Flush(true);
+ } else if (command == "salvage") {
+ return SalvageWallet(path);
+ }
} else {
tfm::format(std::cerr, "Invalid command: %s\n", command);
return false;