Auto-backup wallet.dat before flush/rewrite operations
- Add AutoBackupWallet() that copies wallet.dat to wallet.dat.auto.bak before any DB flush or rewrite - Call AutoBackupWallet() in ThreadFlushWalletDB() before flushing - Call AutoBackupWallet() in AppInit2() after loading wallet - Add suspicious-size check in AppInit2() (warns if wallet.dat < 1KB) - Declare AutoBackupWallet() in db.h This protects against wallet corruption during crash by maintaining an auto-backup that is always at least as recent as the last flush.
This commit is contained in:
@@ -16,6 +16,40 @@ namespace fs = boost::filesystem;
|
||||
static uint64_t nAccountingEntryNumber = 0;
|
||||
extern bool fWalletUnlockStakingOnly;
|
||||
|
||||
//
|
||||
// Auto-backup wallet before flush/rewrite operations.
|
||||
// Copies wallet.dat to wallet.dat.auto.bak if the backup is older than the wallet.
|
||||
// Returns true if backup was created or already up to date.
|
||||
//
|
||||
bool AutoBackupWallet(const fs::path& walletPath)
|
||||
{
|
||||
fs::path backupPath = walletPath.string() + ".auto.bak";
|
||||
try {
|
||||
// Only back up if wallet exists and is non-trivial (>1KB)
|
||||
if (!fs::exists(walletPath))
|
||||
return true;
|
||||
uintmax_t walletSize = fs::file_size(walletPath);
|
||||
if (walletSize < 1024) {
|
||||
printf("AutoBackupWallet: wallet.dat is only %llu bytes (possibly corrupt), skipping auto-backup\n",
|
||||
(unsigned long long)walletSize);
|
||||
return false;
|
||||
}
|
||||
// Skip if backup exists and is same size (already backed up this version)
|
||||
if (fs::exists(backupPath)) {
|
||||
uintmax_t backupSize = fs::file_size(backupPath);
|
||||
if (backupSize == walletSize)
|
||||
return true;
|
||||
}
|
||||
fs::copy_file(walletPath, backupPath, fs::copy_options::overwrite_existing);
|
||||
printf("AutoBackupWallet: backed up wallet.dat (%llu bytes) to wallet.dat.auto.bak\n",
|
||||
(unsigned long long)walletSize);
|
||||
return true;
|
||||
} catch (const fs::filesystem_error& e) {
|
||||
printf("AutoBackupWallet: failed - %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// CWalletDB
|
||||
//
|
||||
@@ -580,6 +614,10 @@ void ThreadFlushWalletDB(void* parg)
|
||||
nLastFlushed = nWalletDBUpdated;
|
||||
int64_t nStart = GetTimeMillis();
|
||||
|
||||
// Auto-backup before flush (protects against corruption)
|
||||
fs::path walletPath = GetDataDir() / strFile;
|
||||
AutoBackupWallet(walletPath);
|
||||
|
||||
// Flush wallet.dat so it's self contained
|
||||
bitdb.CloseDb(strFile);
|
||||
bitdb.CheckpointLSN(strFile);
|
||||
|
||||
Reference in New Issue
Block a user