upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/selftest.cpp
diff options
context:
space:
mode:
authorBitflash <admin@bitflash.network>2026-08-14 16:06:39 -0300
committerBitflash <admin@bitflash.network>2026-08-14 16:06:39 -0300
commit25b1eb8e17bb4012a59166667c7e37564a2af939 (patch)
tree0cf369cd3e1c59eca068cc05561dd59c21bf7b49 /src/selftest.cpp
parentc08a32d26cabf5acc9dabf298a22051596308174 (diff)
parent59b9d11015f0e3a2475d0750fc534583c2ca9f77 (diff)
Merge pull request 'wallet: export BDB records to SQLite' (#48) from wallet-sqlite-migration into main
Diffstat (limited to 'src/selftest.cpp')
-rw-r--r--src/selftest.cpp148
1 files changed, 147 insertions, 1 deletions
diff --git a/src/selftest.cpp b/src/selftest.cpp
index f9c4a8e..7a54271 100644
--- a/src/selftest.cpp
+++ b/src/selftest.cpp
@@ -1134,6 +1134,150 @@ static int RunWalletSQLiteSelfTest()
1134 return nFail == 0 ? 0 : 1; 1134 return nFail == 0 ? 0 : 1;
1135} 1135}
1136 1136
1137class CWalletRecordMapVisitor : public CWalletRecordVisitor
1138{
1139public:
1140 std::map<vector<unsigned char>, vector<unsigned char> >& mapRecords;
1141
1142 explicit CWalletRecordMapVisitor(
1143 std::map<vector<unsigned char>, vector<unsigned char> >& mapRecordsIn)
1144 : mapRecords(mapRecordsIn) { }
1145
1146 bool VisitWalletRecord(const CDataStream& ssKey,
1147 const CDataStream& ssValue,
1148 string& strErrorRet)
1149 {
1150 vector<unsigned char> vchKey = DataStreamBytes(ssKey);
1151 if (mapRecords.count(vchKey))
1152 {
1153 strErrorRet = "duplicate serialized wallet key";
1154 return false;
1155 }
1156 mapRecords[vchKey] = DataStreamBytes(ssValue);
1157 return true;
1158 }
1159};
1160
1161static int RunWalletSQLiteMigrationSelfTest()
1162{
1163 fflush(stdout);
1164 printf("wallet-sqlite-migration self-test\n");
1165
1166 std::string tmp;
1167 std::string cwd;
1168 if (!MakeTempDir(tmp))
1169 {
1170 printf(" FAIL could not create a temporary data directory\n");
1171 return 1;
1172 }
1173 if (!GetCurrentDir(cwd))
1174 {
1175 printf(" FAIL could not read current directory\n");
1176 RemoveTree(tmp);
1177 return 1;
1178 }
1179
1180 int nFail = 0;
1181 printf(" temp root: %s\n", tmp.c_str());
1182
1183 try
1184 {
1185#ifdef _WIN32
1186 string strExe = cwd + "\\bitflash.exe";
1187#else
1188 string strExe = cwd + "/bitflash-node";
1189#endif
1190 string strWalletDir = tmp + "/wallet";
1191 nFail += Check(MakeDirLocal(strWalletDir),
1192 "temporary wallet directory can be created") ? 0 : 1;
1193
1194 string strCreateOut = tmp + "/create.txt";
1195 vector<string> vCreateArgs;
1196 vCreateArgs.push_back("-datadir=" + strWalletDir);
1197 vCreateArgs.push_back("-nomanagedtor");
1198 vCreateArgs.push_back("-nogui");
1199 vCreateArgs.push_back("-newphrase");
1200 int nCreateRet = RunBitflashChild(strExe, vCreateArgs, NULL, &strCreateOut);
1201 nFail += Check(nCreateRet == 0 &&
1202 FileContainsText(strCreateOut, "Write these twelve words down"),
1203 "a phrase wallet can be created for SQLite export") ? 0 : 1;
1204
1205 string strSQLite = tmp + "/wallet.sqlite";
1206 string strExportOut = tmp + "/sqlite-export.txt";
1207 vector<string> vExportArgs;
1208 vExportArgs.push_back("-datadir=" + strWalletDir);
1209 vExportArgs.push_back("-nomanagedtor");
1210 vExportArgs.push_back("-nogui");
1211 vExportArgs.push_back("-walletsqliteexport=" + strSQLite);
1212 int nExportRet = RunBitflashChild(strExe, vExportArgs, NULL, &strExportOut);
1213 nFail += Check(nExportRet == 0 &&
1214 FileExists(strSQLite.c_str()) &&
1215 FileContainsText(strExportOut, "SQLite wallet export written"),
1216 "wallet.dat can be exported to SQLite") ? 0 : 1;
1217
1218 string strOverwriteOut = tmp + "/sqlite-export-overwrite.txt";
1219 int nOverwriteRet =
1220 RunBitflashChild(strExe, vExportArgs, NULL, &strOverwriteOut);
1221 nFail += Check(nOverwriteRet != 0 &&
1222 FileContainsText(strOverwriteOut,
1223 "Refusing to overwrite existing SQLite wallet export"),
1224 "SQLite wallet export refuses to overwrite") ? 0 : 1;
1225 remove((strSQLite + "-wal").c_str());
1226 remove((strSQLite + "-shm").c_str());
1227
1228 std::map<vector<unsigned char>, vector<unsigned char> > mapBDB;
1229 string strOldDataDir = strSetDataDir;
1230 string strScanError;
1231 strSetDataDir = strWalletDir;
1232 CWalletRecordMapVisitor visitor(mapBDB);
1233 bool fScanOk = ScanWalletRecords(visitor, strScanError);
1234 DBFlush(true);
1235 strSetDataDir = strOldDataDir;
1236 nFail += Check(fScanOk && !mapBDB.empty(),
1237 "wallet.dat records can be scanned for comparison") ? 0 : 1;
1238
1239 CWalletDBSQLite db;
1240 string strError;
1241 nFail += Check(db.Open(strSQLite, strError),
1242 "exported SQLite wallet opens") ? 0 : 1;
1243 int nSQLiteRecords = 0;
1244 nFail += Check(db.CountRecords(nSQLiteRecords, strError) &&
1245 nSQLiteRecords == (int)mapBDB.size(),
1246 "SQLite export has the same record count as wallet.dat") ? 0 : 1;
1247
1248 bool fAllMatch = true;
1249 for (std::map<vector<unsigned char>, vector<unsigned char> >::const_iterator it =
1250 mapBDB.begin(); it != mapBDB.end(); ++it)
1251 {
1252 vector<unsigned char> vchSQLiteValue;
1253 if (!db.ReadRecord(it->first, vchSQLiteValue, strError) ||
1254 vchSQLiteValue != it->second)
1255 {
1256 fAllMatch = false;
1257 break;
1258 }
1259 }
1260 nFail += Check(fAllMatch,
1261 "SQLite export preserves every wallet.dat key/value byte-for-byte") ? 0 : 1;
1262 }
1263 catch (const std::exception& e)
1264 {
1265 printf(" FAIL exception: %s\n", e.what());
1266 nFail++;
1267 }
1268 catch (...)
1269 {
1270 printf(" FAIL unknown exception\n");
1271 nFail++;
1272 }
1273
1274 RemoveTree(tmp);
1275 printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED",
1276 nFail, nFail == 1 ? "" : "s");
1277 fflush(stdout);
1278 return nFail == 0 ? 0 : 1;
1279}
1280
1137static void ClearWalletRuntimeForTest() 1281static void ClearWalletRuntimeForTest()
1138{ 1282{
1139 CRITICAL_BLOCK(cs_mapKeys) 1283 CRITICAL_BLOCK(cs_mapKeys)
@@ -2395,6 +2539,8 @@ int RunSelfTest(const std::string& name)
2395 return RunDbEnvReopenSelfTest(); 2539 return RunDbEnvReopenSelfTest();
2396 if (name == "wallet-sqlite") 2540 if (name == "wallet-sqlite")
2397 return RunWalletSQLiteSelfTest(); 2541 return RunWalletSQLiteSelfTest();
2542 if (name == "wallet-sqlite-migration")
2543 return RunWalletSQLiteMigrationSelfTest();
2398 if (name == "wallet-crypto") 2544 if (name == "wallet-crypto")
2399 return RunWalletCryptoSelfTest(); 2545 return RunWalletCryptoSelfTest();
2400 if (name == "wallet-encrypt") 2546 if (name == "wallet-encrypt")
@@ -2415,6 +2561,6 @@ int RunSelfTest(const std::string& name)
2415 return RunManagedTorSelfTest(); 2561 return RunManagedTorSelfTest();
2416 2562
2417 printf("Unknown self-test '%s'\n", name.c_str()); 2563 printf("Unknown self-test '%s'\n", name.c_str());
2418 printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity, db-env-reopen, wallet-sqlite, wallet-crypto, wallet-encrypt, wallet-portability, net-message, consensus-limits, pool-stratum, parse-money, socks5-proxy, managed-tor\n"); 2564 printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity, db-env-reopen, wallet-sqlite, wallet-sqlite-migration, wallet-crypto, wallet-encrypt, wallet-portability, net-message, consensus-limits, pool-stratum, parse-money, socks5-proxy, managed-tor\n");
2419 return 1; 2565 return 1;
2420} 2566}