upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBitflash <admin@bitflash.network>2026-08-14 16:26:51 -0300
committerBitflash <admin@bitflash.network>2026-08-14 16:26:51 -0300
commit0c58896a045246c3518d5d379f217172defdfd91 (patch)
tree37d252761127383f5f8eab98a0e57f33605e1fc0
parent25b1eb8e17bb4012a59166667c7e37564a2af939 (diff)
parentdf84b82162b38dcd57114510b9651af5d85f04cb (diff)
Merge pull request 'wallet: scan SQLite wallet records' (#49) from wallet-sqlite-scan into main
-rw-r--r--docs/storage.md4
-rw-r--r--src/selftest.cpp6
-rw-r--r--src/wallet_sqlite.cpp54
-rw-r--r--src/wallet_sqlite.h3
4 files changed, 66 insertions, 1 deletions
diff --git a/docs/storage.md b/docs/storage.md
index bb414b5..2d748fa 100644
--- a/docs/storage.md
+++ b/docs/storage.md
@@ -108,7 +108,9 @@ BDB-to-SQLite migration or runtime backend flag exists.
108`wallet.dat` record through `ScanWalletRecords()` and writes those same key and 108`wallet.dat` record through `ScanWalletRecords()` and writes those same key and
109value bytes into the SQLite table inside one transaction. It refuses to 109value bytes into the SQLite table inside one transaction. It refuses to
110overwrite an existing export and still does not change the runtime wallet 110overwrite an existing export and still does not change the runtime wallet
111backend. 111backend. `CWalletDBSQLite::ScanRecords()` can stream those exported records back
112through the same visitor shape, so tests can compare BDB and SQLite record
113streams without introducing a SQLite runtime wallet loader yet.
112 114
113## `blkindex.dat` 115## `blkindex.dat`
114 116
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()
1259 } 1259 }
1260 nFail += Check(fAllMatch, 1260 nFail += Check(fAllMatch,
1261 "SQLite export preserves every wallet.dat key/value byte-for-byte") ? 0 : 1; 1261 "SQLite export preserves every wallet.dat key/value byte-for-byte") ? 0 : 1;
1262
1263 std::map<vector<unsigned char>, vector<unsigned char> > mapSQLite;
1264 CWalletRecordMapVisitor sqliteVisitor(mapSQLite);
1265 nFail += Check(db.ScanRecords(sqliteVisitor, strError) &&
1266 mapSQLite == mapBDB,
1267 "SQLite wallet scanner streams every exported record byte-for-byte") ? 0 : 1;
1262 } 1268 }
1263 catch (const std::exception& e) 1269 catch (const std::exception& e)
1264 { 1270 {
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<unsigned char>& vchKey,
231 return false; 231 return false;
232} 232}
233 233
234bool CWalletDBSQLite::ScanRecords(CWalletRecordVisitor& visitor,
235 string& strError)
236{
237 if (!pdb)
238 {
239 strError = "SQLite wallet is not open";
240 return false;
241 }
242
243 sqlite3_stmt* stmt = NULL;
244 const char* pszSql = "SELECT key, value FROM wallet_records ORDER BY rowid;";
245 int ret = sqlite3_prepare_v2(pdb, pszSql, -1, &stmt, NULL);
246 if (ret != SQLITE_OK)
247 {
248 SetSQLiteError(pdb, "cannot prepare SQLite wallet scan", strError);
249 return false;
250 }
251
252 while ((ret = sqlite3_step(stmt)) == SQLITE_ROW)
253 {
254 const unsigned char* pchKey =
255 (const unsigned char*)sqlite3_column_blob(stmt, 0);
256 int nKeyBytes = sqlite3_column_bytes(stmt, 0);
257 const unsigned char* pchValue =
258 (const unsigned char*)sqlite3_column_blob(stmt, 1);
259 int nValueBytes = sqlite3_column_bytes(stmt, 1);
260
261 vector<unsigned char> vchKey;
262 vector<unsigned char> vchValue;
263 if (nKeyBytes > 0 && pchKey)
264 vchKey.assign(pchKey, pchKey + nKeyBytes);
265 if (nValueBytes > 0 && pchValue)
266 vchValue.assign(pchValue, pchValue + nValueBytes);
267
268 CDataStream ssKey(vchKey, SER_DISK);
269 CDataStream ssValue(vchValue, SER_DISK);
270 if (!visitor.VisitWalletRecord(ssKey, ssValue, strError))
271 {
272 sqlite3_finalize(stmt);
273 return false;
274 }
275 }
276
277 if (ret != SQLITE_DONE)
278 {
279 SetSQLiteError(pdb, "cannot scan SQLite wallet records", strError);
280 sqlite3_finalize(stmt);
281 return false;
282 }
283
284 sqlite3_finalize(stmt);
285 return true;
286}
287
234bool CWalletDBSQLite::CountRecords(int& nRecordsRet, string& strError) 288bool CWalletDBSQLite::CountRecords(int& nRecordsRet, string& strError)
235{ 289{
236 nRecordsRet = 0; 290 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 @@
6 6
7#include <sqlite3.h> 7#include <sqlite3.h>
8 8
9class CWalletRecordVisitor;
10
9class CWalletDBSQLite 11class CWalletDBSQLite
10{ 12{
11public: 13public:
@@ -26,6 +28,7 @@ public:
26 bool ReadRecord(const vector<unsigned char>& vchKey, 28 bool ReadRecord(const vector<unsigned char>& vchKey,
27 vector<unsigned char>& vchValueRet, 29 vector<unsigned char>& vchValueRet,
28 string& strError); 30 string& strError);
31 bool ScanRecords(CWalletRecordVisitor& visitor, string& strError);
29 bool CountRecords(int& nRecordsRet, string& strError); 32 bool CountRecords(int& nRecordsRet, string& strError);
30 33
31private: 34private: