fix(node): restore the LARGEST salvage backup, not the newest (salvage cascade)
The "Restore original wallet" action picked the newest wallet.<ts>.bak — but the daemon auto-salvages on every failed BDB verify, and each round SHRINKS the wallet (salvage keeps only readable records + drops the dead-page bloat). In a cascade the newest .bak is the most-degraded (seen in the wild as "Salvage found no records") while the original is the oldest and by far the largest. Pick by file SIZE instead: add largestWalletSalvageBak((name,size) pairs) — the largest wallet.<digits>.bak is the least-salvaged, i.e. the pristine original (an emptied salvage is tiny; a real wallet is large); ties break to the newest ts. Factor the shared parse into parseWalletSalvageBakTs(). restoreOriginalWallet() now gathers file sizes and uses it (still verifies the pick is a valid BDB before swapping). newestWalletSalvageBak kept for reference. Adds a cascade regression test (a 40KB emptied newest .bak must NOT win over the 194MB original). Suite green (1/1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4575,14 +4575,21 @@ void App::restoreOriginalWallet()
|
||||
std::string err, warn;
|
||||
try {
|
||||
const std::string datadir = util::Platform::getDragonXDataDir();
|
||||
// 1. Find the newest salvage backup (offline — no daemon needed).
|
||||
std::vector<std::string> files;
|
||||
// 1. Find the LARGEST salvage backup (offline — no daemon needed). Largest = least-salvaged =
|
||||
// the original: a salvage cascade shrinks the wallet each round, so the newest .bak can be
|
||||
// empty ("Salvage found no records") while the original is untouched and huge.
|
||||
std::vector<std::pair<std::string, unsigned long long>> files;
|
||||
{
|
||||
std::error_code lec;
|
||||
for (const auto& e : fs::directory_iterator(datadir, lec))
|
||||
if (!lec) files.push_back(e.path().filename().string());
|
||||
for (const auto& e : fs::directory_iterator(datadir, lec)) {
|
||||
if (lec) break;
|
||||
std::error_code se;
|
||||
const auto sz = fs::is_regular_file(e, se) ? fs::file_size(e, se) : 0;
|
||||
files.emplace_back(e.path().filename().string(),
|
||||
se ? 0ull : static_cast<unsigned long long>(sz));
|
||||
}
|
||||
}
|
||||
const std::string bak = daemon::newestWalletSalvageBak(files);
|
||||
const std::string bak = daemon::largestWalletSalvageBak(files);
|
||||
if (bak.empty()) {
|
||||
err = TR("wallet_restore_no_backup");
|
||||
} else if (!util::probeWalletFile(datadir + "/" + bak).isBerkeleyDB) {
|
||||
|
||||
Reference in New Issue
Block a user