perf(history): weekly safety-net full re-sweep for sent history
Persisting the sent-sweep watermark means a relaunch runs a windowed sweep, which can't see a change made outside the GUI (a Console z_importviewingkey, an external same-seed restore) that adds an old send below the window. This adds a periodic full re-sweep so that case is still caught within ~7 days. - sentSweepSafetyNetDue(now, lastFull) = lastFull > 0 && now - lastFull > 7d (a wallet that has never full-swept doesn't trigger one; the seeding sweep records the time). lastFullTime / lastFullHeight ride in the sent_sweep snapshot; any successful full sweep (seed, verify-mismatch or safety-net) resets the clock. On load, a valid watermark without a clock starts it now, so even watermarks seeded before this field eventually re-sweep. - When due, the snapshot forces a full sweep for that cycle. Gated on: a watermark exists, a routine (non-syncing) cycle, not the Mining page, and not in full-sweep backoff -- so a full sweep that can't finish on a slow daemon backs off instead of retrying every cycle. Degrades gracefully: ~0.4 s on a note-cache daemon; callLong(120 s) with backoff on an old one (the deferred banding would keep each cs_main hold short so it fits there too). Helper + persistence covered by tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -65,6 +65,11 @@ bool sentSweepNeedsLongCall(int tip, int fromHeight)
|
||||
return tip > 0 && fromHeight >= 0 && (tip - fromHeight) > kSentSweepLongCallBlocks;
|
||||
}
|
||||
|
||||
bool sentSweepSafetyNetDue(std::int64_t nowSec, std::int64_t lastFullSec)
|
||||
{
|
||||
return lastFullSec > 0 && (nowSec - lastFullSec) > kSentSweepSafetyNetSec;
|
||||
}
|
||||
|
||||
long fullSentSweepRetryDelaySec(int consecutiveFailures)
|
||||
{
|
||||
if (consecutiveFailures <= 0) return 0;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@@ -31,6 +32,8 @@ constexpr int kSentSweepReorgMarginBlocks = 100; // > MAX_REORG_LENGTH (99),
|
||||
constexpr int kSentSweepFirstLoadExtraBlocks = 1000; // E: extra margin on the first sweep after a load,
|
||||
// to absorb wallet-notifier lag at the last save
|
||||
constexpr int kSentSweepLongCallBlocks = 2400; // tip - W beyond this: use callLong + count failures
|
||||
constexpr long kSentSweepSafetyNetSec = 7 * 24 * 3600; // ~weekly full re-sweep: catches external wallet
|
||||
// changes the per-event guards can't see
|
||||
constexpr long kFullSentSweepTimeoutSec = 120; // a whole-wallet sweep must be able to finish
|
||||
constexpr int kTransparentPageMin = 1000;
|
||||
constexpr int kTransparentPageMax = 5000;
|
||||
@@ -64,6 +67,10 @@ int sentSweepAnchor(int fromHeight, bool firstAfterLoad);
|
||||
// A watermark saved long ago makes a huge "windowed" call: past this gap, use callLong and count failures
|
||||
// toward the backoff, so it doesn't time out on every block while the daemon keeps working.
|
||||
bool sentSweepNeedsLongCall(int tip, int fromHeight);
|
||||
// A watermarked wallet is due a periodic full re-sweep to catch changes made outside the GUI (a Console
|
||||
// import, an external same-seed restore) that the per-event guards miss. lastFullSec == 0 (no full sweep
|
||||
// recorded yet) never triggers one: the seeding full sweep records it.
|
||||
bool sentSweepSafetyNetDue(std::int64_t nowSec, std::int64_t lastFullSec);
|
||||
// Backoff after full sweeps that failed in a way that cost the daemon the work: 0, 10 min, 1 h, then 6 h.
|
||||
long fullSentSweepRetryDelaySec(int consecutiveFailures);
|
||||
// Whether a failed full sweep counts toward that backoff: only when the daemon did the work (reply timeout,
|
||||
|
||||
Reference in New Issue
Block a user