From 84a60275569dca5d1fb12db38ce184caf7487ed6 Mon Sep 17 00:00:00 2001 From: bitflash Date: Tue, 18 Aug 2026 14:44:11 -0300 Subject: wallet: one-shot storage commands honour -walletbackend=sqlite -walletstorageaudit, -walletstoragecheck and -backupwallet all read wallet.dat regardless of the selected backend. Under -walletbackend=sqlite that is wrong, and for backup it is dangerous: it silently backs up the stale plaintext wallet.dat instead of the live wallet.sqlite. - ScanWalletRecords() routes to the active SQLite store instead of a Berkeley DB cursor (it returned an error under the runtime before). This is the single choke point audit and check scan through. - WalletSQLiteRuntimeOpenReadOnly() opens wallet.sqlite for scanning without loading or validating records, so the pre-load diagnostics can inspect a wallet the loader would refuse. main_gui opens it for audit/check when the SQLite backend is selected (and rejects an unknown backend value there too). - BackupWallet() copies wallet.sqlite (checkpoint, then the temp/old/rename dance; a checkpointed SQLite file is self-contained, no lsn_reset). wallet-sqlite-encrypt self-test proves routing on a datadir where the SQLite wallet is encrypted and wallet.dat beside it is still plaintext: audit with the flag reports the encrypted seed, without it reports the plaintext one; the SQLite backup carries no plaintext key and loadchecks as a standalone wallet. --- src/main_gui.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'src/main_gui.cpp') diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 4be4995..af6053f 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -524,19 +524,57 @@ int main(int argc, char* argv[]) // explain wallet.dat states that the normal wallet loader may refuse. string strWalletStorageAuditJson = argval2(argc, argv, "/walletstorageauditjson", "-walletstorageauditjson"); - if (arg(argc,argv,"/walletstorageaudit") || - arg(argc,argv,"-walletstorageaudit") || - !strWalletStorageAuditJson.empty()) + bool fDiagWantsAudit = arg(argc,argv,"/walletstorageaudit") || + arg(argc,argv,"-walletstorageaudit") || + !strWalletStorageAuditJson.empty(); + bool fDiagWantsCheck = arg(argc,argv,"/walletstoragecheck") || + arg(argc,argv,"-walletstoragecheck"); + + // These diagnostics normally read wallet.dat. Under -walletbackend=sqlite + // the live wallet is wallet.sqlite, so open it read-only as the active + // store and let the same scan walk the right file. This runs before the + // normal backend resolution further down, so validate the value here too. + string strDiagBackend = argval2(argc, argv, "/walletbackend", "-walletbackend"); + if ((fDiagWantsAudit || fDiagWantsCheck) && !strDiagBackend.empty() && + strDiagBackend != "sqlite" && strDiagBackend != "bdb") + { + AttachTerminal(); + fprintf(stderr, "Unknown wallet backend '%s'. Use -walletbackend=sqlite " + "or -walletbackend=bdb.\n", strDiagBackend.c_str()); + return 1; + } + bool fDiagSQLite = (strDiagBackend == "sqlite") && + (fDiagWantsAudit || fDiagWantsCheck); + if (fDiagSQLite) + { + AttachTerminal(); + string strSQLitePath = GetAppDir() + "/wallet.sqlite"; + string strOpenErr; + if (!WalletSQLiteRuntimeOpenReadOnly(strSQLitePath, strOpenErr)) + { + fprintf(stderr, "Cannot open the SQLite wallet for diagnostics: %s\n", + strOpenErr.c_str()); + return 1; + } + } + + if (fDiagWantsAudit) { int nRet = CmdWalletStorageAudit(strWalletStorageAuditJson); - DBFlush(true); + if (fDiagSQLite) + WalletSQLiteRuntimeClose(); + else + DBFlush(true); return nRet; } - if (arg(argc,argv,"/walletstoragecheck") || arg(argc,argv,"-walletstoragecheck")) + if (fDiagWantsCheck) { int nRet = CmdWalletStorageCheck(); - DBFlush(true); + if (fDiagSQLite) + WalletSQLiteRuntimeClose(); + else + DBFlush(true); return nRet; } -- cgit v1.2.3