From df84b82162b38dcd57114510b9651af5d85f04cb Mon Sep 17 00:00:00 2001 From: Nsable-sh Date: Fri, 14 Aug 2026 16:20:41 -0300 Subject: wallet: scan SQLite wallet records --- src/selftest.cpp | 6 ++++++ src/wallet_sqlite.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/wallet_sqlite.h | 3 +++ 3 files changed, 63 insertions(+) (limited to 'src') diff --git a/src/selftest.cpp b/src/selftest.cpp index 7a54271..408dd41 100644 --- a/src/selftest.cpp +++ b/src/selftest.cpp @@ -1259,6 +1259,12 @@ static int RunWalletSQLiteMigrationSelfTest() } nFail += Check(fAllMatch, "SQLite export preserves every wallet.dat key/value byte-for-byte") ? 0 : 1; + + std::map, vector > mapSQLite; + CWalletRecordMapVisitor sqliteVisitor(mapSQLite); + nFail += Check(db.ScanRecords(sqliteVisitor, strError) && + mapSQLite == mapBDB, + "SQLite wallet scanner streams every exported record byte-for-byte") ? 0 : 1; } catch (const std::exception& e) { diff --git a/src/wallet_sqlite.cpp b/src/wallet_sqlite.cpp index 4369af6..8489cac 100644 --- a/src/wallet_sqlite.cpp +++ b/src/wallet_sqlite.cpp @@ -231,6 +231,60 @@ bool CWalletDBSQLite::ReadRecord(const vector& vchKey, return false; } +bool CWalletDBSQLite::ScanRecords(CWalletRecordVisitor& visitor, + string& strError) +{ + if (!pdb) + { + strError = "SQLite wallet is not open"; + return false; + } + + sqlite3_stmt* stmt = NULL; + const char* pszSql = "SELECT key, value FROM wallet_records ORDER BY rowid;"; + int ret = sqlite3_prepare_v2(pdb, pszSql, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + SetSQLiteError(pdb, "cannot prepare SQLite wallet scan", strError); + return false; + } + + while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) + { + const unsigned char* pchKey = + (const unsigned char*)sqlite3_column_blob(stmt, 0); + int nKeyBytes = sqlite3_column_bytes(stmt, 0); + const unsigned char* pchValue = + (const unsigned char*)sqlite3_column_blob(stmt, 1); + int nValueBytes = sqlite3_column_bytes(stmt, 1); + + vector vchKey; + vector vchValue; + if (nKeyBytes > 0 && pchKey) + vchKey.assign(pchKey, pchKey + nKeyBytes); + if (nValueBytes > 0 && pchValue) + vchValue.assign(pchValue, pchValue + nValueBytes); + + CDataStream ssKey(vchKey, SER_DISK); + CDataStream ssValue(vchValue, SER_DISK); + if (!visitor.VisitWalletRecord(ssKey, ssValue, strError)) + { + sqlite3_finalize(stmt); + return false; + } + } + + if (ret != SQLITE_DONE) + { + SetSQLiteError(pdb, "cannot scan SQLite wallet records", strError); + sqlite3_finalize(stmt); + return false; + } + + sqlite3_finalize(stmt); + return true; +} + bool CWalletDBSQLite::CountRecords(int& nRecordsRet, string& strError) { nRecordsRet = 0; diff --git a/src/wallet_sqlite.h b/src/wallet_sqlite.h index 5ef862d..385a340 100644 --- a/src/wallet_sqlite.h +++ b/src/wallet_sqlite.h @@ -6,6 +6,8 @@ #include +class CWalletRecordVisitor; + class CWalletDBSQLite { public: @@ -26,6 +28,7 @@ public: bool ReadRecord(const vector& vchKey, vector& vchValueRet, string& strError); + bool ScanRecords(CWalletRecordVisitor& visitor, string& strError); bool CountRecords(int& nRecordsRet, string& strError); private: -- cgit v1.2.3