From 544e12a4e81633d222574eec253a1ff292d3c4a5 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Tue, 25 Aug 2020 13:10:32 -0400 Subject: walletdb: Add KeyFilterFn to ReadKeyValue Add a KeyFilterFn callback to ReadKeyValue which allows the caller to specify which types to actually deserialize. A KeyFilterFn takes the type as the parameter and returns a bool indicating whether deserialization should continue. --- src/wallet/walletdb.cpp | 10 +++++++--- src/wallet/walletdb.h | 5 ++++- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index fa6814d0d3..4635c19b3d 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -263,13 +263,17 @@ public: static bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, - CWalletScanState &wss, std::string& strType, std::string& strErr) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) + CWalletScanState &wss, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { try { // Unserialize // Taking advantage of the fact that pair serialization // is just the two items serialized one after the other ssKey >> strType; + // If we have a filter, check if this matches the filter + if (filter_fn && !filter_fn(strType)) { + return true; + } if (strType == DBKeys::NAME) { std::string strAddress; ssKey >> strAddress; @@ -668,11 +672,11 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, return true; } -bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr) +bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn) { CWalletScanState dummy_wss; LOCK(pwallet->cs_wallet); - return ReadKeyValue(pwallet, ssKey, ssValue, dummy_wss, strType, strErr); + return ReadKeyValue(pwallet, ssKey, ssValue, dummy_wss, strType, strErr, filter_fn); } bool WalletBatch::IsKeyType(const std::string& strType) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 64d60b1f44..eaeb2bb863 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -280,8 +280,11 @@ private: //! Compacts BDB state so that wallet.dat is self-contained (if there are changes) void MaybeCompactWalletDB(); +//! Callback for filtering key types to deserialize in ReadKeyValue +using KeyFilterFn = std::function; + //! Unserialize a given Key-Value pair and load it into the wallet -bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr); +bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr); /** Return whether a wallet database is currently loaded. */ bool IsWalletLoaded(const fs::path& wallet_path); -- cgit v1.2.3 From 0bbe26a1af2aab2287b18048f80b3f70e63e0044 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Tue, 25 Aug 2020 13:15:50 -0400 Subject: wallet: filter for keys only before record deser in salvage When salvaging a wallet, avoid deserializing any records that we don't care about, i.e. filter for keys only before the deserialization. --- src/wallet/salvage.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp index c0755db751..934e3d5c86 100644 --- a/src/wallet/salvage.cpp +++ b/src/wallet/salvage.cpp @@ -16,6 +16,11 @@ static const char *HEADER_END = "HEADER=END"; static const char *DATA_END = "DATA=END"; typedef std::pair, std::vector > KeyValPair; +static bool KeyFilter(const std::string& type) +{ + return WalletBatch::IsKeyType(type) || type == DBKeys::HDCHAIN; +} + bool RecoverDatabaseFile(const fs::path& file_path, bilingual_str& error, std::vector& warnings) { std::string filename; @@ -129,9 +134,9 @@ bool RecoverDatabaseFile(const fs::path& file_path, bilingual_str& error, std::v { // Required in LoadKeyMetadata(): LOCK(dummyWallet.cs_wallet); - fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue, strType, strErr); + fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue, strType, strErr, KeyFilter); } - if (!WalletBatch::IsKeyType(strType) && strType != DBKeys::HDCHAIN) { + if (!KeyFilter(strType)) { continue; } if (!fReadOK) -- cgit v1.2.3