Skip to content

dig-node: wallet_coins answers zero for every CAT while unsynced — the mirror image of #2879 #306

Description

@MichaelTaylor3d

Task

WalletBackend::wallet_coins (dig-node crates/dig-wallet/src/sage/rpc.rs) answers zero for
any CAT while the local replica is unsynced, because its fallback branch bails out rather than
reading:

Source::Fallback => {
    // CAT asset attribution while syncing needs puzzle uncurrying (follow-on), so
    // the syncing-fallback CAT set is empty until the DB converges.
    if asset_id.is_some() {
        return Ok(Vec::new());
    }

This is the mirror image of #2879: not a holding the user does not have, but a holding they
DO have reported as nothing. It reaches get_spendable_coin_count and the Sage-parity token
surface, so a real $DIG holder on an unsynced node reads as holding none.

Context

Found while sweeping rpc.rs for #2879's defect shape (PR #224). It is a
different defect class from #2879 — an under-report, not an over-report — which is why it was
logged rather than folded into that PR.

The blocker named in that comment no longer exists. #2879 established that "puzzle uncurrying"
is unnecessary: a CAT coin's asset is identified by where the coin sits, not by uncurrying it.
digstore_chain::cat::cat_puzzle_hash(owner_p2_hash, asset_id) gives the puzzle hash a given
asset's coins live at, so a hint read can be filtered to one asset with no uncurrying at all.
PR#224 added exactly that filter as WalletBackend::asset_scoped_fallback_coins; this call site
takes an arbitrary asset_id: Option<&str> rather than a BalanceAsset, so it needs the hex
parsed to Bytes32 first — the only real work here.

See also the canonical skill, "A hint is not an asset — where a CAT coin lives".

Scope

Wire the fallback CAT arm to a filtered hint read. Note the blast radius is wider than #2879's:
wallet_coins feeds spend-input selection, so this changes what a spend can select while
unsynced — worth a careful look at whether an unconfirmed/unattributed coin should be selectable,
which is a judgement #2879 did not have to make.

Evidence

A test proving a $DIG holder on an unsynced replica sees their coins, plus a control proving a
foreign CAT hinted to the same address does not appear as theirs (both directions, as in #224).


Orchestrator ticket: https://github.com/DIG-Network/dig_ecosystem/issues/205

Moved from DIG-Network/dig_ecosystem#2902 so this repo's own PR can close it with Closes (CLAUDE.md §1.3).
GitHub refuses a private-to-public issue transfer, so the body was copied and comment history
stayed on the original.

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