Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13711386
D8596.id26174.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
16 KB
Subscribers
None
D8596.id26174.diff
View Options
diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt
--- a/src/wallet/CMakeLists.txt
+++ b/src/wallet/CMakeLists.txt
@@ -20,6 +20,7 @@
load.cpp
rpcdump.cpp
rpcwallet.cpp
+ salvage.cpp
scriptpubkeyman.cpp
wallet.cpp
walletdb.cpp
diff --git a/src/wallet/db.h b/src/wallet/db.h
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -411,10 +411,4 @@
const char *pszSkip = nullptr);
};
-bool RecoverDatabaseFile(const fs::path &file_path, void *callbackDataIn,
- bool (*recoverKVcallback)(void *callbackData,
- CDataStream ssKey,
- CDataStream ssValue),
- std::string &out_backup_filename);
-
#endif // BITCOIN_WALLET_DB_H
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -338,145 +338,6 @@
return &m_dbt;
}
-/* End of headers, beginning of key/value data */
-static const char *HEADER_END = "HEADER=END";
-/* End of key/value data */
-static const char *DATA_END = "DATA=END";
-typedef std::pair<std::vector<uint8_t>, std::vector<uint8_t>> KeyValPair;
-
-bool RecoverDatabaseFile(const fs::path &file_path, void *callbackDataIn,
- bool (*recoverKVcallback)(void *callbackData,
- CDataStream ssKey,
- CDataStream ssValue),
- std::string &newFilename) {
- std::string filename;
- std::shared_ptr<BerkeleyEnvironment> env =
- GetWalletEnv(file_path, filename);
-
- // Recovery procedure:
- // Move wallet file to walletfilename.timestamp.bak
- // Call Salvage with fAggressive=true to get as much data as possible.
- // Rewrite salvaged data to fresh wallet file.
- // Set -rescan so any missing transactions will be found.
- int64_t now = GetTime();
- newFilename = strprintf("%s.%d.bak", filename, now);
-
- int result = env->dbenv->dbrename(nullptr, filename.c_str(), nullptr,
- newFilename.c_str(), DB_AUTO_COMMIT);
- if (result == 0) {
- LogPrintf("Renamed %s to %s\n", filename, newFilename);
- } else {
- LogPrintf("Failed to rename %s to %s\n", filename, newFilename);
- return false;
- }
-
- /**
- * Salvage data from a file. The DB_AGGRESSIVE flag is being used (see
- * berkeley DB->verify() method documentation). key/value pairs are appended
- * to salvagedData which are then written out to a new wallet file. NOTE:
- * reads the entire database into memory, so cannot be used for huge
- * databases.
- */
- std::vector<KeyValPair> salvagedData;
-
- std::stringstream strDump;
-
- Db db(env->dbenv.get(), 0);
- result = db.verify(newFilename.c_str(), nullptr, &strDump,
- DB_SALVAGE | DB_AGGRESSIVE);
- if (result == DB_VERIFY_BAD) {
- LogPrintf("Salvage: Database salvage found "
- "errors, all data may not be recoverable.\n");
- }
- if (result != 0 && result != DB_VERIFY_BAD) {
- LogPrintf("Salvage: Database salvage failed with "
- "result %d.\n",
- result);
- return false;
- }
-
- // Format of bdb dump is ascii lines:
- // header lines...
- // HEADER=END
- // hexadecimal key
- // hexadecimal value
- // ... repeated
- // DATA=END
-
- std::string strLine;
- while (!strDump.eof() && strLine != HEADER_END) {
- // Skip past header
- getline(strDump, strLine);
- }
-
- std::string keyHex, valueHex;
- while (!strDump.eof() && keyHex != DATA_END) {
- getline(strDump, keyHex);
- if (keyHex != DATA_END) {
- if (strDump.eof()) {
- break;
- }
- getline(strDump, valueHex);
- if (valueHex == DATA_END) {
- LogPrintf("Salvage: WARNING: Number of "
- "keys in data does not match number of values.\n");
- break;
- }
- salvagedData.push_back(
- make_pair(ParseHex(keyHex), ParseHex(valueHex)));
- }
- }
-
- bool fSuccess;
- if (keyHex != DATA_END) {
- LogPrintf("Salvage: WARNING: Unexpected end of "
- "file while reading salvage output.\n");
- fSuccess = false;
- } else {
- fSuccess = (result == 0);
- }
-
- if (salvagedData.empty()) {
- LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename);
- return false;
- }
- LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size());
-
- std::unique_ptr<Db> pdbCopy = std::make_unique<Db>(env->dbenv.get(), 0);
- int ret = pdbCopy->open(nullptr, // Txn pointer
- filename.c_str(), // Filename
- "main", // Logical db name
- DB_BTREE, // Database type
- DB_CREATE, // Flags
- 0);
- if (ret > 0) {
- LogPrintf("Cannot create database file %s\n", filename);
- pdbCopy->close(0);
- return false;
- }
-
- DbTxn *ptxn = env->TxnBegin();
- for (KeyValPair &row : salvagedData) {
- if (recoverKVcallback) {
- CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION);
- CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION);
- if (!(*recoverKVcallback)(callbackDataIn, ssKey, ssValue)) {
- continue;
- }
- }
- Dbt datKey(&row.first[0], row.first.size());
- Dbt datValue(&row.second[0], row.second.size());
- int ret2 = pdbCopy->put(ptxn, &datKey, &datValue, DB_NOOVERWRITE);
- if (ret2 > 0) {
- fSuccess = false;
- }
- }
- ptxn->commit(0);
- pdbCopy->close(0);
-
- return fSuccess;
-}
-
bool BerkeleyBatch::VerifyEnvironment(const fs::path &file_path,
bilingual_str &errorStr) {
std::string walletFile;
diff --git a/src/wallet/salvage.h b/src/wallet/salvage.h
new file mode 100644
--- /dev/null
+++ b/src/wallet/salvage.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_WALLET_SALVAGE_H
+#define BITCOIN_WALLET_SALVAGE_H
+
+#include <fs.h>
+#include <streams.h>
+
+bool RecoverDatabaseFile(const fs::path &file_path, void *callbackDataIn,
+ bool (*recoverKVcallback)(void *callbackData,
+ CDataStream ssKey,
+ CDataStream ssValue),
+ std::string &out_backup_filename);
+
+/* Recover filter (used as callback), will only let keys (cryptographical keys)
+ * as KV/key-type pass through */
+bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey,
+ CDataStream ssValue);
+
+#endif // BITCOIN_WALLET_SALVAGE_H
diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp
new file mode 100644
--- /dev/null
+++ b/src/wallet/salvage.cpp
@@ -0,0 +1,170 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <fs.h>
+#include <streams.h>
+#include <wallet/salvage.h>
+#include <wallet/wallet.h>
+#include <wallet/walletdb.h>
+
+/* End of headers, beginning of key/value data */
+static const char *HEADER_END = "HEADER=END";
+/* End of key/value data */
+static const char *DATA_END = "DATA=END";
+typedef std::pair<std::vector<uint8_t>, std::vector<uint8_t>> KeyValPair;
+
+bool RecoverDatabaseFile(const fs::path &file_path, void *callbackDataIn,
+ bool (*recoverKVcallback)(void *callbackData,
+ CDataStream ssKey,
+ CDataStream ssValue),
+ std::string &newFilename) {
+ std::string filename;
+ std::shared_ptr<BerkeleyEnvironment> env =
+ GetWalletEnv(file_path, filename);
+
+ // Recovery procedure:
+ // move wallet file to walletfilename.timestamp.bak
+ // Call Salvage with fAggressive=true to
+ // get as much data as possible.
+ // Rewrite salvaged data to fresh wallet file
+ // Set -rescan so any missing transactions will be
+ // found.
+ int64_t now = GetTime();
+ newFilename = strprintf("%s.%d.bak", filename, now);
+
+ int result = env->dbenv->dbrename(nullptr, filename.c_str(), nullptr,
+ newFilename.c_str(), DB_AUTO_COMMIT);
+ if (result == 0) {
+ LogPrintf("Renamed %s to %s\n", filename, newFilename);
+ } else {
+ LogPrintf("Failed to rename %s to %s\n", filename, newFilename);
+ return false;
+ }
+
+ /**
+ * Salvage data from a file. The DB_AGGRESSIVE flag is being used (see
+ * berkeley DB->verify() method documentation). key/value pairs are appended
+ * to salvagedData which are then written out to a new wallet file. NOTE:
+ * reads the entire database into memory, so cannot be used for huge
+ * databases.
+ */
+ std::vector<KeyValPair> salvagedData;
+
+ std::stringstream strDump;
+
+ Db db(env->dbenv.get(), 0);
+ result = db.verify(newFilename.c_str(), nullptr, &strDump,
+ DB_SALVAGE | DB_AGGRESSIVE);
+ if (result == DB_VERIFY_BAD) {
+ LogPrintf("Salvage: Database salvage found errors, all data may not be "
+ "recoverable.\n");
+ }
+ if (result != 0 && result != DB_VERIFY_BAD) {
+ LogPrintf("Salvage: Database salvage failed with result %d.\n", result);
+ return false;
+ }
+
+ // Format of bdb dump is ascii lines:
+ // header lines...
+ // HEADER=END
+ // hexadecimal key
+ // hexadecimal value
+ // ... repeated
+ // DATA=END
+
+ std::string strLine;
+ while (!strDump.eof() && strLine != HEADER_END) {
+ getline(strDump, strLine); // Skip past header
+ }
+
+ std::string keyHex, valueHex;
+ while (!strDump.eof() && keyHex != DATA_END) {
+ getline(strDump, keyHex);
+ if (keyHex != DATA_END) {
+ if (strDump.eof()) {
+ break;
+ }
+ getline(strDump, valueHex);
+ if (valueHex == DATA_END) {
+ LogPrintf("Salvage: WARNING: Number of keys in data does not "
+ "match number of values.\n");
+ break;
+ }
+ salvagedData.push_back(
+ make_pair(ParseHex(keyHex), ParseHex(valueHex)));
+ }
+ }
+
+ bool fSuccess;
+ if (keyHex != DATA_END) {
+ LogPrintf("Salvage: WARNING: Unexpected end of file while reading "
+ "salvage output.\n");
+ fSuccess = false;
+ } else {
+ fSuccess = (result == 0);
+ }
+
+ if (salvagedData.empty()) {
+ LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename);
+ return false;
+ }
+ LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size());
+
+ std::unique_ptr<Db> pdbCopy = std::make_unique<Db>(env->dbenv.get(), 0);
+ int ret = pdbCopy->open(nullptr, // Txn pointer
+ filename.c_str(), // Filename
+ "main", // Logical db name
+ DB_BTREE, // Database type
+ DB_CREATE, // Flags
+ 0);
+ if (ret > 0) {
+ LogPrintf("Cannot create database file %s\n", filename);
+ pdbCopy->close(0);
+ return false;
+ }
+
+ DbTxn *ptxn = env->TxnBegin();
+ for (KeyValPair &row : salvagedData) {
+ if (recoverKVcallback) {
+ CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION);
+ CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION);
+ if (!(*recoverKVcallback)(callbackDataIn, ssKey, ssValue)) {
+ continue;
+ }
+ }
+ Dbt datKey(&row.first[0], row.first.size());
+ Dbt datValue(&row.second[0], row.second.size());
+ int ret2 = pdbCopy->put(ptxn, &datKey, &datValue, DB_NOOVERWRITE);
+ if (ret2 > 0) {
+ fSuccess = false;
+ }
+ }
+ ptxn->commit(0);
+ pdbCopy->close(0);
+
+ return fSuccess;
+}
+
+bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey,
+ CDataStream ssValue) {
+ CWallet *dummyWallet = reinterpret_cast<CWallet *>(callbackData);
+ std::string strType, strErr;
+ bool fReadOK;
+ {
+ // Required in LoadKeyMetadata():
+ LOCK(dummyWallet->cs_wallet);
+ fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue, strType, strErr);
+ }
+ if (!WalletBatch::IsKeyType(strType) && strType != DBKeys::HDCHAIN) {
+ return false;
+ }
+ if (!fReadOK) {
+ LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", strType,
+ strErr);
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -55,6 +55,38 @@
NEED_REWRITE
};
+namespace DBKeys {
+extern const std::string ACENTRY;
+extern const std::string ACTIVEEXTERNALSPK;
+extern const std::string ACTIVEINTERNALSPK;
+extern const std::string BESTBLOCK;
+extern const std::string BESTBLOCK_NOMERKLE;
+extern const std::string CRYPTED_KEY;
+extern const std::string CSCRIPT;
+extern const std::string DEFAULTKEY;
+extern const std::string DESTDATA;
+extern const std::string FLAGS;
+extern const std::string HDCHAIN;
+extern const std::string KEY;
+extern const std::string KEYMETA;
+extern const std::string MASTER_KEY;
+extern const std::string MINVERSION;
+extern const std::string NAME;
+extern const std::string OLD_KEY;
+extern const std::string ORDERPOSNEXT;
+extern const std::string POOL;
+extern const std::string PURPOSE;
+extern const std::string SETTINGS;
+extern const std::string TX;
+extern const std::string VERSION;
+extern const std::string WALLETDESCRIPTOR;
+extern const std::string WALLETDESCRIPTORCACHE;
+extern const std::string WALLETDESCRIPTORCKEY;
+extern const std::string WALLETDESCRIPTORKEY;
+extern const std::string WATCHMETA;
+extern const std::string WATCHS;
+} // namespace DBKeys
+
/* simple HD chain data model */
class CHDChain {
public:
@@ -279,9 +311,4 @@
bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue,
std::string &strType, std::string &strErr);
-/* Recover filter (used as callback), will only let keys (cryptographical keys)
- * as KV/key-type pass through */
-bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey,
- CDataStream ssValue);
-
#endif // BITCOIN_WALLET_WALLETDB_H
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -965,28 +965,6 @@
fOneThread = false;
}
-bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey,
- CDataStream ssValue) {
- CWallet *dummyWallet = reinterpret_cast<CWallet *>(callbackData);
- std::string strType, strErr;
- bool fReadOK;
- {
- // Required in LoadKeyMetadata():
- LOCK(dummyWallet->cs_wallet);
- fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue, strType, strErr);
- }
- if (!WalletBatch::IsKeyType(strType) && strType != DBKeys::HDCHAIN) {
- return false;
- }
- if (!fReadOK) {
- LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", strType,
- strErr);
- return false;
- }
-
- return true;
-}
-
bool WalletBatch::VerifyEnvironment(const fs::path &wallet_path,
bilingual_str &errorStr) {
return BerkeleyBatch::VerifyEnvironment(wallet_path, errorStr);
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
--- a/src/wallet/wallettool.cpp
+++ b/src/wallet/wallettool.cpp
@@ -6,6 +6,7 @@
#include <fs.h>
#include <util/system.h>
#include <util/translation.h>
+#include <wallet/salvage.h>
#include <wallet/wallet.h>
#include <wallet/walletutil.h>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 26, 11:50 (2 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5573455
Default Alt Text
D8596.id26174.diff (16 KB)
Attached To
D8596: Move RecoverDatabaseFile and RecoverKeysOnlyFilter into salvage.{cpp/h}
Event Timeline
Log In to Comment