From 95bd9cbcb1d17f4bc6223e6bfe3a92bfb8c3067d Mon Sep 17 00:00:00 2001 From: Nsable-sh Date: Fri, 14 Aug 2026 09:08:29 -0300 Subject: wallet: add read-only record scan boundary --- src/db.cpp | 39 ++++++++++++++++++++++++++++++++++ src/db.h | 11 ++++++++++ src/walletcmd.cpp | 63 ++++++++++++++++++++++--------------------------------- 3 files changed, 75 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/db.cpp b/src/db.cpp index 9f62964..4fa72af 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -932,6 +932,45 @@ bool CWalletDB::LoadWallet(vector& vchDefaultKeyRet) return true; } +bool ScanWalletRecords(CWalletRecordVisitor& visitor, string& strErrorRet) +{ + class CWalletScanDB : public CWalletDB + { + public: + CWalletScanDB() : CWalletDB("r") { } + using CDB::GetCursor; + using CDB::ReadAtCursor; + }; + + strErrorRet.clear(); + CWalletScanDB dbWallet; + Dbc* pcursor = dbWallet.GetCursor(); + if (!pcursor) + { + strErrorRet = "could not open a wallet cursor"; + return false; + } + CAutoCursor cursorGuard(pcursor); + + loop + { + CDataStream ssKey(SER_DISK); + CDataStream ssValue(SER_DISK); + int ret = dbWallet.ReadAtCursor(pcursor, ssKey, ssValue); + if (ret == DB_NOTFOUND) + break; + if (ret != 0) + { + strErrorRet = strprintf("could not read wallet record: Berkeley DB error %d", ret); + return false; + } + if (!visitor.VisitWalletRecord(ssKey, ssValue, strErrorRet)) + return false; + } + + return true; +} + bool LoadWallet() { vector vchDefaultKey; diff --git a/src/db.h b/src/db.h index 4fb5cfd..2816957 100644 --- a/src/db.h +++ b/src/db.h @@ -524,6 +524,17 @@ public: bool LoadWallet(vector& vchDefaultKeyRet); }; +class CWalletRecordVisitor +{ +public: + virtual ~CWalletRecordVisitor() { } + virtual bool VisitWalletRecord(const CDataStream& ssKey, + const CDataStream& ssValue, + string& strErrorRet) = 0; +}; + +bool ScanWalletRecords(CWalletRecordVisitor& visitor, string& strErrorRet); + bool LoadWallet(); // Writes a wallet.dat that opens on its own, anywhere -- see the definition in diff --git a/src/walletcmd.cpp b/src/walletcmd.cpp index ce0da02..71f1ec3 100644 --- a/src/walletcmd.cpp +++ b/src/walletcmd.cpp @@ -553,51 +553,38 @@ static void CountWalletStorageType(const std::string& strType, static bool ReadWalletStorageCounts(WalletStorageAuditCounts& counts, std::string& strError) { - class CWalletAuditDB : public CWalletDB + class CWalletStorageCountVisitor : public CWalletRecordVisitor { public: - CWalletAuditDB() : CWalletDB("r") { } - using CDB::GetCursor; - using CDB::ReadAtCursor; - }; - - CWalletAuditDB walletdb; - Dbc* pcursor = walletdb.GetCursor(); - if (!pcursor) - { - strError = "cannot open wallet.dat cursor"; - return false; - } + WalletStorageAuditCounts& counts; - for (;;) - { - CDataStream ssKey(SER_DISK); - CDataStream ssValue(SER_DISK); - int ret = walletdb.ReadAtCursor(pcursor, ssKey, ssValue); - if (ret == DB_NOTFOUND) - break; - if (ret != 0) - { - pcursor->close(); - strError = strprintf("Berkeley DB cursor read failed (%d)", ret); - return false; - } + explicit CWalletStorageCountVisitor(WalletStorageAuditCounts& countsIn) + : counts(countsIn) { } - counts.nTotal++; - try + bool VisitWalletRecord(const CDataStream& ssKeyIn, + const CDataStream& ssValue, + std::string& strErrorRet) { - std::string strType; - ssKey >> strType; - CountWalletStorageType(strType, counts); - } - catch (...) - { - counts.nMalformed++; + (void)ssValue; + (void)strErrorRet; + counts.nTotal++; + try + { + CDataStream ssKey = ssKeyIn; + std::string strType; + ssKey >> strType; + CountWalletStorageType(strType, counts); + } + catch (...) + { + counts.nMalformed++; + } + return true; } - } + }; - pcursor->close(); - return true; + CWalletStorageCountVisitor visitor(counts); + return ScanWalletRecords(visitor, strError); } static std::string WalletStorageAuditJson(const WalletStorageAuditCounts& counts) -- cgit v1.2.3