diff options
| author | Bitflash <admin@bitflash.network> | 2026-08-14 16:06:39 -0300 |
|---|---|---|
| committer | Bitflash <admin@bitflash.network> | 2026-08-14 16:06:39 -0300 |
| commit | 25b1eb8e17bb4012a59166667c7e37564a2af939 (patch) | |
| tree | 0cf369cd3e1c59eca068cc05561dd59c21bf7b49 /src/selftest.cpp | |
| parent | c08a32d26cabf5acc9dabf298a22051596308174 (diff) | |
| parent | 59b9d11015f0e3a2475d0750fc534583c2ca9f77 (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.cpp | 148 |
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 | ||
| 1137 | class CWalletRecordMapVisitor : public CWalletRecordVisitor | ||
| 1138 | { | ||
| 1139 | public: | ||
| 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 | |||
| 1161 | static 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 | |||
| 1137 | static void ClearWalletRuntimeForTest() | 1281 | static 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 | } |