From 2636844f5353797a0b8e40a879652a0d345172ad Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Mon, 18 Apr 2022 14:56:23 -0400 Subject: [PATCH] walletdb: Remove loading code where the database is iterated Instead of iterating the database to load the wallet, we now load particular kinds of records in an order that we want them to be loaded. So it is no longer necessary to iterate the entire database to load the wallet. --- src/wallet/walletdb.cpp | 101 ---------------------------------------- 1 file changed, 101 deletions(-) diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index fb1e4f8fb57..2aee750ced9 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -298,13 +298,6 @@ bool WalletBatch::EraseLockedUTXO(const COutPoint& output) return EraseIC(std::make_pair(DBKeys::LOCKED_UTXO, std::make_pair(output.hash, output.n))); } -class CWalletScanState { -public: - unsigned int m_unknown_records{0}; - - CWalletScanState() = default; -}; - bool LoadKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr) { LOCK(pwallet->cs_wallet); @@ -453,61 +446,6 @@ bool LoadHDChain(CWallet* pwallet, DataStream& ssValue, std::string& strErr) return true; } -static bool -ReadKeyValue(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, - CWalletScanState &wss, std::string& strType, std::string& strErr) 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 (pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) && DBKeys::LEGACY_TYPES.count(strType) > 0) { - return true; - } - if (strType == DBKeys::NAME) { - } else if (strType == DBKeys::PURPOSE) { - } else if (strType == DBKeys::TX) { - } else if (strType == DBKeys::WATCHS) { - } else if (strType == DBKeys::KEY) { - } else if (strType == DBKeys::MASTER_KEY) { - } else if (strType == DBKeys::CRYPTED_KEY) { - } else if (strType == DBKeys::KEYMETA) { - } else if (strType == DBKeys::WATCHMETA) { - } else if (strType == DBKeys::DEFAULTKEY) { - } else if (strType == DBKeys::POOL) { - } else if (strType == DBKeys::CSCRIPT) { - } else if (strType == DBKeys::ORDERPOSNEXT) { - } else if (strType == DBKeys::DESTDATA) { - } else if (strType == DBKeys::HDCHAIN) { - } else if (strType == DBKeys::OLD_KEY) { - } else if (strType == DBKeys::ACTIVEEXTERNALSPK || strType == DBKeys::ACTIVEINTERNALSPK) { - } else if (strType == DBKeys::WALLETDESCRIPTOR) { - } else if (strType == DBKeys::WALLETDESCRIPTORCACHE) { - } else if (strType == DBKeys::WALLETDESCRIPTORLHCACHE) { - } else if (strType == DBKeys::WALLETDESCRIPTORKEY) { - } else if (strType == DBKeys::WALLETDESCRIPTORCKEY) { - } else if (strType == DBKeys::LOCKED_UTXO) { - } else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE && - strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY && - strType != DBKeys::VERSION && strType != DBKeys::SETTINGS && - strType != DBKeys::FLAGS) { - wss.m_unknown_records++; - } - } catch (const std::exception& e) { - if (strErr.empty()) { - strErr = e.what(); - } - return false; - } catch (...) { - if (strErr.empty()) { - strErr = "Caught unknown exception in ReadKeyValue"; - } - return false; - } - return true; -} - static DBErrors LoadMinVersion(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { AssertLockHeld(pwallet->cs_wallet); @@ -1198,8 +1136,6 @@ static DBErrors LoadDecryptionKeys(CWallet* pwallet, DatabaseBatch& batch) EXCLU DBErrors WalletBatch::LoadWallet(CWallet* pwallet) { - CWalletScanState wss; - bool fNoncriticalErrors = false; DBErrors result = DBErrors::LOAD_OK; bool any_unordered = false; std::vector upgraded_txs; @@ -1246,49 +1182,12 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet) // Load decryption keys result = std::max(LoadDecryptionKeys(pwallet, *m_batch), result); - - // Get cursor - std::unique_ptr cursor = m_batch->GetNewCursor(); - if (!cursor) - { - pwallet->WalletLogPrintf("Error getting wallet database cursor\n"); - return DBErrors::CORRUPT; - } - - while (true) - { - // Read next record - DataStream ssKey{}; - CDataStream ssValue(SER_DISK, CLIENT_VERSION); - DatabaseCursor::Status status = cursor->Next(ssKey, ssValue); - if (status == DatabaseCursor::Status::DONE) { - break; - } else if (status == DatabaseCursor::Status::FAIL) { - cursor.reset(); - pwallet->WalletLogPrintf("Error reading next record from wallet database\n"); - return DBErrors::CORRUPT; - } - - // Try to be tolerant of single corrupt records: - std::string strType, strErr; - if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr)) - { - // Leave other errors alone, if we try to fix them we might make things worse. - fNoncriticalErrors = true; // ... but do warn the user there is something wrong. - } - if (!strErr.empty()) - pwallet->WalletLogPrintf("%s\n", strErr); - } } catch (...) { // Exceptions that can be ignored or treated as non-critical are handled by the individual loading functions. // Any uncaught exceptions will be caught here and treated as critical. result = DBErrors::CORRUPT; } - if (fNoncriticalErrors && result == DBErrors::LOAD_OK) { - result = DBErrors::NONCRITICAL_ERROR; - } - // Any wallet corruption at all: skip any rewriting or // upgrading, we don't want to make it worse. if (result != DBErrors::LOAD_OK)