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:
@@ -6156,6 +6156,18 @@ void testBlockDbOutputDiagnosis()
|
||||
EXPECT_EQ(newestWalletSalvageBak({"wallet.dat", "wallet.dat.encrypted.bak", "notes.txt"}),
|
||||
std::string("")); // no wallet.<digits>.bak present
|
||||
EXPECT_EQ(newestWalletSalvageBak({}), std::string(""));
|
||||
|
||||
// Restore must pick the LARGEST (least-salvaged) backup, NOT the newest — a salvage cascade shrinks
|
||||
// the wallet each round, so the newest .bak can be an emptied 40KB copy while the original is huge.
|
||||
using dragonx::daemon::largestWalletSalvageBak;
|
||||
EXPECT_EQ(largestWalletSalvageBak({
|
||||
{"wallet.dat", 40000ull}, // current (salvaged, tiny) — not a .bak
|
||||
{"wallet.1786200000.bak", 194174976ull}, // ORIGINAL — oldest ts, biggest
|
||||
{"wallet.1786340620.bak", 40960ull}, // latest salvage — newest ts, empty
|
||||
{"peers.dat", 999ull}}),
|
||||
std::string("wallet.1786200000.bak")); // largest wins over newest
|
||||
EXPECT_EQ(largestWalletSalvageBak({{"wallet.dat", 100ull}, {"notes.txt", 5ull}}), std::string(""));
|
||||
EXPECT_EQ(largestWalletSalvageBak({}), std::string(""));
|
||||
}
|
||||
|
||||
// Live probe of a real lite server (env-gated). Validates CONNECT_ONLY latency + IP capture.
|
||||
|
||||
Reference in New Issue
Block a user