Skip to content

SQLite persister never writes gap-extended addresses, so CoinJoin address rows stop at the registration window #5723

Open

Description

@PastaPastaPasta

Problem. After a reload, a SQLite-backed wallet's core_address_pool knows only the addresses that existed at registration. Addresses derived later by gap-limit extension during sync are never stored. For a CoinJoin account (seeded with 100 addresses) the table stops at index 99, however far mixing has gone. Everything that resolves ownership from the table (UTXO→account routing, used-address restore, address-reuse guard) then has nothing for indices ≥ 100.

Reproduction. Create a wallet with a CoinJoin account, sync a CoinJoin history that spends indices ≥ 100 so the pool gap-extends, close, reopen. Compare SELECT max(address_index) FROM core_address_pool WHERE account_type='coinjoin' (99) with the in-memory pool's highest generated index before close.

Cause. packages/rs-platform-wallet-storage/src/sqlite/schema/core_state.rs:113-115 states that addresses_derived is intentionally not persisted and that account_address_pools is "the derived-address source". But account_address_pools snapshots are only emitted at registration, the DashPay contact paths and the asset-lock funding-index path (wallet_lifecycle.rs:649, contacts.rs:80, prepared_payment.rs:831, asset_lock/build.rs:755,820), never from the SPV transaction/block path. The sync path produces only CoreChangeSet.addresses_derived (changeset/core_bridge.rs:1721,1781), which the SQLite persister ignores. This was removed on purpose in #3828 for a different reason (a rescan-time flush loop in a single-account design).

Suggested fix. Upsert each addresses_derived entry as a core_address_pool row (it carries account_type, pool_type, derivation_index, address, public_key), inside the same changeset transaction, using the existing monotonic UPSERT_POOL_SQL conflict policy (used never regresses). That also makes the used flag meaningful for sync-derived rows (addresses_marked_used is likewise unread by this persister). Or emit whole-pool account_address_pools snapshots when a pool grows.

Related: #3828 (retired this on purpose), #5549 / #5210 (also change pool restore, same files). With this fixed, route_to_funds_account would find owners for these coins; the fallback for coins it still cannot route is #5724.

Line numbers are at v5.1-dev e72022a.

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