Skip to content

platform-wallet: a one-way DashPay contact never gets our receiving account, so its payments to us are never seen #5246

Closed

Description

@HashEngineering

Summary

Suppose we send a DashPay contact request and the contact never sends one back. That contact never gets a DashpayReceivingFunds account in the SDK wallet. Our receiving chain for that contact is never watched, and any payment the contact sends us on it is invisible at every rescan depth.

DIP-15 puts our receiving xpub inside the contact request we send. A contact who has our request can therefore pay us whether or not they ever reciprocate. platform-wallet assumes the opposite in two places.

Where

  1. Account building. collect_account_build_candidates (packages/rs-platform-wallet/src/wallet/identity/network/contact_requests.rs) walks established_contacts() only. A contact that exists only in sent_contact_requests() is never a candidate, so RegisterReceiving is never queued for it.
  2. Rescan. reconcile_dashpay_rescan (.../network/payments.rs) skips every receival account whose contact is not in established_contacts(). Even an account built some other way would get no backfill for the blocks before it was registered.

The live send path (send_contact_request_with_external_signer) registers the receiving account itself, so a wallet that sends the request in the current session is fine. The gap appears when the sent request is learned from Platform by the contact sweep (restore from seed, a second device, a migrated wallet), or when the live registration failed after the request had been saved.

A contact who only sent us a request is not affected: they never received our xpub, so there is no chain of ours for them to pay.

Example (testnet, topple wallet 7dc06ad3…)

  • Tx e5169bfc4989585abd4b0476188611b981e3c750539da5b8a39fe135e3bbb957, height 1,475,820: 0.001 DASH to yMNNc2UZz62V9N7SZfQnsk79G5okCP7eSN. That is our receiving chain 15'/0'/(us)/(4193bbe6…)/0 for contact 5QzA7GnST….
  • The SDK store holds one contact request for that contact: ours, at core height 1,475,801, 19 blocks before the payment. It has no incoming request and no DashPay account rows for the contact.
  • The transaction is missing from every archived SDK store of this wallet (about 40 builds, int6 through int27). dashj's wallet dump has it and watches the same chain.
  • Its later spend, 6ac8356c…, is stored with netAmount = +99734 instead of minus the fee, because the funding transaction is unknown.
  • The balance is correct today only because that coin has since been spent. An unspent payment on such a chain would be missing money.
  • Two more contacts on the same wallet (c7037829…, ce3cff2f…) are in the same one-way state.

The host's dark-contact diagnostic cannot see this case either: it lists established contacts that lack receival accounts, and these contacts are not established.

Expected

For every contact we have sent a request to, the wallet should register our DashpayReceivingFunds account (the external account still needs their request) and rescan from the height of our request.

Related

Activity

  1. HashEngineering commented on Nov 4, 2026

    @HashEngineering
    CollaboratorAuthor

    Fixed by #4740 (merged into v5.1-dev on 2026-10-27), which builds a DashpayReceivingFunds account for every contact holding our request, including one-way contacts, and backfills from our earliest sent request. #5256 was closed as superseded.

    Verified on device with a kotlin-sdk build (5.1.0-int33) based on v5.1-dev with #4740 and without #5256: on a Wallet A restore, e5169bfc… appears at height 1,476,252 (+100000), the spend 6ac8356c… shows −266 instead of +99734, and all three one-way contacts have receiving accounts.

    🤖 Posted by Claude Code

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