Skip to content

Reset the cached coin database and re-sync from chain (control method + dign verb) #384

Description

@MichaelTaylor3d

Task

Give the node a way to drop the cached coin database and re-sync it from chain, exposed as a
control method and a dign verb. The DIG App button (dig-app#TBD) drives this; it must not reach into
the database itself.

User directive, 2026-08-27 (verbatim): "we will need to reset the database when this is fixed.
There should be a button in dig-app to reset the coin datbase and resync"

Parent epic: https://github.com/DIG-Network/dig_ecosystem/issues/3170
Related: #382 (the CAT attribution defect that prompted it)

Why this is worth building even though #382's fix backfills

reconstruct_all walks every coin in the DB and attributes any that is unspent, unattributed and
a candidate — so once #382 wires the attributor, existing asset_id = NULL rows are repaired on the
next update tick without a reset. A reset is not the remedy for #382.

The case that genuinely needs it is narrower and permanent:

let Some(parent) = lineage.parent_spend(&c.parent_coin_info, created as u32).await? else {
    continue;
};

A coin whose parent spend could not be fetched — source unreachable, a transient failure, a pruned
response — is skipped, silently, and never retried. Nothing re-queues it. That coin stays
unattributed for the life of the database, so its asset never resolves and its value never appears in
an asset-scoped balance. There is currently no way for a user to recover from that except deleting
the file by hand.

That is the honest justification: not "the DB is stale" but "a one-off fetch failure is permanent
and otherwise unrecoverable."

The hazard this MUST get right — the repo already documents it

Between emptying the table and finishing the re-sync, the database is empty. The routing gate
(WalletDb::is_syncedrouting::route) is what makes the local replica authoritative. So an
emptied-but-still-synced database answers balance 0, synced true on a funded wallet.

sync.rs already states this for the reorg-rollback path, in almost these words:

"The routing gate … is what makes an emptied DB authoritative, so a destructive push must clear it:
the wallet then reads from the fallback tier until a genuine catch-up re-establishes the flag.
Without this, one hostile frame makes a funded wallet answer balance 0, synced true."

The reset must clear is_synced in the same transaction that empties the coins, so a crash
between the two cannot leave an empty authoritative replica. Reads then fall back until a real
catch-up re-establishes the flag. This is the money-lie class (§2.6's narrow stop) and it is the whole
risk of the feature.

Other constraints

  • Never touch key material. Coins are chain-derived and safe to discard; a seed is not. Scope the
    reset to chain-cached tables and say explicitly which ones.
  • Refuse while a spend is in flight. coin_reservations, client_coin_reservations and
    pending_transactions reference coins by id. Wiping the coins beneath a reserved, unconfirmed spend
    loses the record of what is committed and invites a double-spend attempt. Refuse with a clear
    machine-branchable error rather than resetting anyway.
  • Re-entrant. Pressing it twice, or while a resync is running, must not corrupt or start two
    catch-ups.
  • Report progress. A resync from genesis is slow. The caller needs to distinguish "running" from
    "stalled" — dign wallet sync-status already reports phase and replica height; make the reset
    observable through the same read rather than inventing a second status surface.

Deliverables

Acceptance

On a real funded wallet: reset, watch the balance become unknown (never a confident zero), watch the
resync complete, and see the same balance and coins as before. §2.6 — evidence is that sequence on a
real machine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:businessa person can DO something new, or money moves, or a shipped surface stops lying to themmvpgates the releasable MVP

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions