mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-08 10:31:50 -05:00
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.
This commit is contained in:
parent
cd211b3b99
commit
2636844f53
1 changed files with 0 additions and 101 deletions
|
@ -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<uint256> 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<DatabaseCursor> 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)
|
||||
|
|
Loading…
Add table
Reference in a new issue