Skip to content

Rescan blockchain does not widen the scan of a date-restored wallet #1572

Description

@HashEngineering

Summary

A wallet restored with a Wallet Creation Date set only scans the chain from that date
forward. Settings → Rescan blockchain with the date cleared is the way to widen it back out.
It does not work: the app arms the rewind, the SDK reports no error, but the scan never replays
the earlier range. The wallet keeps its partial balance and truncated history indefinitely.

There is currently no in-app recovery from a wrong creation date. The only remedy found is to
restore the wallet again from the recovery phrase with the date left unset.

Found while testing a separate UI fix; reproduced on two builds, neither of which touches the
rescan path.

Environment

  • Android 16 (API 36) emulator, _testNet3 release, versionCode 12000014 (12.0.0-upgrade)
  • Reproduced on fix/upgrade-memory-and-sync @ 70569d6 and on a branch off it @ 3f4c603a5
  • Testnet, large shared QA wallet (~108 tDASH, history back to 2020)

Steps to reproduce

  1. Fresh install.
  2. Restore a wallet with plenty of old history, and on the restore screen set Wallet Creation
    Date
    to today.
  3. Wait for L1Shadow phase=SYNCED 100.0%. Note the partial balance, and that
    BirthHeightResolver mapped the date to birth height 1,401,408 of a 1,558,713 tip.
  4. Settings → Rescan blockchain. Tap the X beside the pre-filled date so the field reads
    "Select" (no date). Tap Rescan.
  5. Watch /data/data/<pkg>/files/log/wallet.log.

Observed

The arm looks correct:

BirthHeightResolver - resolved birth time 1427610960 to SDK birth height 0 (checkpoint height 1728, margin 4032 blocks)
DashSdkServiceImpl  - armSpvRescan: filter watermark rewind to 0 armed on b7118ed5…
SdkWalletBinder     - blockchain-reset rescan arm on b7118ed5…: armed=true

The scan does not follow it. Over 40 minutes the filter cursor oscillated in a ~15k-block
window sitting at the dated bind's own birth height, never descending:

10:25:47 phase=FILTERS 97.0% headers 1558715/1558715 filters 1416407/1558715 wallet 1558715
10:31:17 phase=FILTERS 96.6% headers 1558717/1558717 filters 1401407/1558717 wallet 1558715
...
11:04:29 phase=FILTERS 96.6% headers 1558733/1558733 filters 1401407/1558733 wallet 1558715

The committed wallet cursor stayed at tip throughout and memory was flat (~340 MB PSS) — so
nothing is being replayed; this is not a slow replay or a leak. Network Monitor read
"Scanning block filters 94%, Block filters 1,401,407 / 1,558,733". Balance unchanged.

Second trial, arming the rescan and then closing from recents and relaunching (in case the
rewind applies at engine start): the engine settled straight back to
phase=SYNCED 100.0% filters 1558738/1558738 within a minute. Balance unchanged, oldest history
row unchanged.

Expected

After a rescan with no date, the scan restarts from the earliest HD seed height and the wallet
ends up with the same balance and history as a dateless restore of the same seed.

Control — the engine can do the full scan

The same wallet, restored fresh with the date left unset, scans from genesis and finishes in
6 minutes 24 seconds:

11:06:35 restore complete (birth height 0)
11:08:10 phase=HEADERS 39.0% headers 1214000/1558734 filters 90999/1558734 wallet 90999
11:12:59 phase=SYNCED 100.0% headers 1558736/1558736 filters 1558736/1558736 wallet 1558736
dated restore + dateless rescan dateless restore
balance 22.704714 tDASH 22.704714 tDASH 108.051627 tDASH
oldest history row 20 Sep 2026 20 Sep 2026 Feb 2020
scan floor height 1,401,408 armed 0, unchanged height 0

So it is specifically the rewind of an already-bound wallet that does not take.

Where to look

The app side appears to do the right thing. SdkWalletBinder.armSpvRescanForBlockchainReset() →
DashSdkServiceImpl.armSpvRescan() (DashSdkServiceImpl.kt:867) resolves the birth height
through the same checkpoint mapping the bind used, then calls:

manager.rescanSpvFilters(walletId, birthHeight.toInt())   // birthHeight = 0 here

That call returns without throwing — the success log line is emitted — so the defect is at or
below rescanSpvFilters. The suspect is the SDK wallet's own stored birthHeight, fixed at
1,401,408 when the wallet was created during the dated restore and never lowered: if the rewind
target is clamped to it, that would explain the cursor sitting exactly there.

Worth confirming whether rescanSpvFilters is expected to lower a wallet's birth height at all,
or whether the app has to re-create/re-bind the wallet to widen the scan.

Related

A wallet in this state also reported a bare "Synced" with no indication that most of the chain
was never scanned. That reporting half is being fixed separately. That fix derives its warning
from the stored creation-date preference, because the scan floor the engine actually used is
not exposed to the app
— so a dateless rescan clears the preference and retires the warning
while leaving the wallet just as partial.

Exposing the bound wallet's real birthHeight (or the height its filter scan actually started
from) would fix both this issue and that gap.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions